PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/akka-docs/rst/java/futures.rst

https://github.com/migue/akka
ReStructuredText | 292 lines | 201 code | 91 blank | 0 comment | 0 complexity | 000010ac9f93231694c9a2268a71fdf0 MD5 | raw file
  1. .. _futures-java:
  2. Futures
  3. ===============
  4. Introduction
  5. ------------
  6. In the Scala Standard Library, a `Future <http://en.wikipedia.org/wiki/Futures_and_promises>`_ is a data structure
  7. used to retrieve the result of some concurrent operation. This result can be accessed synchronously (blocking)
  8. or asynchronously (non-blocking). To be able to use this from Java, Akka provides a java friendly interface
  9. in ``akka.dispatch.Futures``.
  10. Execution Contexts
  11. ------------------
  12. In order to execute callbacks and operations, Futures need something called an ``ExecutionContext``,
  13. which is very similar to a ``java.util.concurrent.Executor``. if you have an ``ActorSystem`` in scope,
  14. it will use its default dispatcher as the ``ExecutionContext``, or you can use the factory methods provided
  15. by the ``ExecutionContexts`` class to wrap ``Executors`` and ``ExecutorServices``, or even create your own.
  16. .. includecode:: code/docs/future/FutureDocTest.java
  17. :include: imports1,imports7
  18. .. includecode:: code/docs/future/FutureDocTest.java
  19. :include: diy-execution-context
  20. Use with Actors
  21. ---------------
  22. There are generally two ways of getting a reply from an ``UntypedActor``: the first is by a sent message (``actorRef.tell(msg, sender)``),
  23. which only works if the original sender was an ``UntypedActor``) and the second is through a ``Future``.
  24. Using the ``ActorRef``\'s ``ask`` method to send a message will return a ``Future``.
  25. To wait for and retrieve the actual result the simplest method is:
  26. .. includecode:: code/docs/future/FutureDocTest.java
  27. :include: imports1
  28. .. includecode:: code/docs/future/FutureDocTest.java
  29. :include: ask-blocking
  30. This will cause the current thread to block and wait for the ``UntypedActor`` to 'complete' the ``Future`` with it's reply.
  31. Blocking is discouraged though as it can cause performance problem.
  32. The blocking operations are located in ``Await.result`` and ``Await.ready`` to make it easy to spot where blocking occurs.
  33. Alternatives to blocking are discussed further within this documentation.
  34. Also note that the ``Future`` returned by an ``UntypedActor`` is a ``Future<Object>`` since an ``UntypedActor`` is dynamic.
  35. That is why the cast to ``String`` is used in the above sample.
  36. .. warning::
  37. ``Await.result`` and ``Await.ready`` are provided for exceptional situations where you **must** block,
  38. a good rule of thumb is to only use them if you know why you **must** block. For all other cases, use
  39. asynchronous composition as described below.
  40. To send the result of a ``Future`` to an ``Actor``, you can use the ``pipe`` construct:
  41. .. includecode:: code/docs/future/FutureDocTest.java
  42. :include: pipe-to
  43. Use Directly
  44. ------------
  45. A common use case within Akka is to have some computation performed concurrently without needing
  46. the extra utility of an ``UntypedActor``. If you find yourself creating a pool of ``UntypedActor``\s for the sole reason
  47. of performing a calculation in parallel, there is an easier (and faster) way:
  48. .. includecode:: code/docs/future/FutureDocTest.java
  49. :include: imports2
  50. .. includecode:: code/docs/future/FutureDocTest.java
  51. :include: future-eval
  52. In the above code the block passed to ``future`` will be executed by the default ``Dispatcher``,
  53. with the return value of the block used to complete the ``Future`` (in this case, the result would be the string: "HelloWorld").
  54. Unlike a ``Future`` that is returned from an ``UntypedActor``, this ``Future`` is properly typed,
  55. and we also avoid the overhead of managing an ``UntypedActor``.
  56. You can also create already completed Futures using the ``Futures`` class, which can be either successes:
  57. .. includecode:: code/docs/future/FutureDocTest.java
  58. :include: successful
  59. Or failures:
  60. .. includecode:: code/docs/future/FutureDocTest.java
  61. :include: failed
  62. It is also possible to create an empty ``Promise``, to be filled later, and obtain the corresponding ``Future``:
  63. .. includecode:: code/docs/future/FutureDocTest.java#promise
  64. For these examples ``PrintResult`` is defined as follows:
  65. .. includecode:: code/docs/future/FutureDocTest.java
  66. :include: print-result
  67. Functional Futures
  68. ------------------
  69. Scala's ``Future`` has several monadic methods that are very similar to the ones used by ``Scala``'s collections.
  70. These allow you to create 'pipelines' or 'streams' that the result will travel through.
  71. Future is a Monad
  72. ^^^^^^^^^^^^^^^^^
  73. The first method for working with ``Future`` functionally is ``map``. This method takes a ``Mapper`` which performs
  74. some operation on the result of the ``Future``, and returning a new result.
  75. The return value of the ``map`` method is another ``Future`` that will contain the new result:
  76. .. includecode:: code/docs/future/FutureDocTest.java
  77. :include: imports2
  78. .. includecode:: code/docs/future/FutureDocTest.java
  79. :include: map
  80. In this example we are joining two strings together within a ``Future``. Instead of waiting for f1 to complete,
  81. we apply our function that calculates the length of the string using the ``map`` method.
  82. Now we have a second ``Future``, f2, that will eventually contain an ``Integer``.
  83. When our original ``Future``, f1, completes, it will also apply our function and complete the second ``Future``
  84. with its result. When we finally ``get`` the result, it will contain the number 10.
  85. Our original ``Future`` still contains the string "HelloWorld" and is unaffected by the ``map``.
  86. Something to note when using these methods: if the ``Future`` is still being processed when one of these methods are called,
  87. it will be the completing thread that actually does the work.
  88. If the ``Future`` is already complete though, it will be run in our current thread. For example:
  89. .. includecode:: code/docs/future/FutureDocTest.java
  90. :include: map2
  91. The original ``Future`` will take at least 0.1 second to execute now, which means it is still being processed at
  92. the time we call ``map``. The function we provide gets stored within the ``Future`` and later executed automatically
  93. by the dispatcher when the result is ready.
  94. If we do the opposite:
  95. .. includecode:: code/docs/future/FutureDocTest.java
  96. :include: map3
  97. Our little string has been processed long before our 0.1 second sleep has finished. Because of this,
  98. the dispatcher has moved onto other messages that need processing and can no longer calculate
  99. the length of the string for us, instead it gets calculated in the current thread just as if we weren't using a ``Future``.
  100. Normally this works quite well as it means there is very little overhead to running a quick function.
  101. If there is a possibility of the function taking a non-trivial amount of time to process it might be better
  102. to have this done concurrently, and for that we use ``flatMap``:
  103. .. includecode:: code/docs/future/FutureDocTest.java
  104. :include: flat-map
  105. Now our second ``Future`` is executed concurrently as well. This technique can also be used to combine the results
  106. of several Futures into a single calculation, which will be better explained in the following sections.
  107. If you need to do conditional propagation, you can use ``filter``:
  108. .. includecode:: code/docs/future/FutureDocTest.java
  109. :include: filter
  110. Composing Futures
  111. ^^^^^^^^^^^^^^^^^
  112. It is very often desirable to be able to combine different Futures with each other,
  113. below are some examples on how that can be done in a non-blocking fashion.
  114. .. includecode:: code/docs/future/FutureDocTest.java
  115. :include: imports3
  116. .. includecode:: code/docs/future/FutureDocTest.java
  117. :include: sequence
  118. To better explain what happened in the example, ``Future.sequence`` is taking the ``Iterable<Future<Integer>>``
  119. and turning it into a ``Future<Iterable<Integer>>``. We can then use ``map`` to work with the ``Iterable<Integer>`` directly,
  120. and we aggregate the sum of the ``Iterable``.
  121. The ``traverse`` method is similar to ``sequence``, but it takes a sequence of ``A`` and applies a function from ``A`` to ``Future<B>``
  122. and returns a ``Future<Iterable<B>>``, enabling parallel ``map`` over the sequence, if you use ``Futures.future`` to create the ``Future``.
  123. .. includecode:: code/docs/future/FutureDocTest.java
  124. :include: imports4
  125. .. includecode:: code/docs/future/FutureDocTest.java
  126. :include: traverse
  127. It's as simple as that!
  128. Then there's a method that's called ``fold`` that takes a start-value,
  129. a sequence of ``Future``:s and a function from the type of the start-value, a timeout,
  130. and the type of the futures and returns something with the same type as the start-value,
  131. and then applies the function to all elements in the sequence of futures, non-blockingly,
  132. the execution will be started when the last of the Futures is completed.
  133. .. includecode:: code/docs/future/FutureDocTest.java
  134. :include: imports5
  135. .. includecode:: code/docs/future/FutureDocTest.java
  136. :include: fold
  137. That's all it takes!
  138. If the sequence passed to ``fold`` is empty, it will return the start-value, in the case above, that will be empty String.
  139. In some cases you don't have a start-value and you're able to use the value of the first completing ``Future``
  140. in the sequence as the start-value, you can use ``reduce``, it works like this:
  141. .. includecode:: code/docs/future/FutureDocTest.java
  142. :include: imports6
  143. .. includecode:: code/docs/future/FutureDocTest.java
  144. :include: reduce
  145. Same as with ``fold``, the execution will be started when the last of the Futures is completed, you can also parallelize
  146. it by chunking your futures into sub-sequences and reduce them, and then reduce the reduced results again.
  147. This is just a sample of what can be done.
  148. Callbacks
  149. ---------
  150. Sometimes you just want to listen to a ``Future`` being completed, and react to that not by creating a new Future, but by side-effecting.
  151. For this Scala supports ``onComplete``, ``onSuccess`` and ``onFailure``, of which the latter two are specializations of the first.
  152. .. includecode:: code/docs/future/FutureDocTest.java
  153. :include: onSuccess
  154. .. includecode:: code/docs/future/FutureDocTest.java
  155. :include: onFailure
  156. .. includecode:: code/docs/future/FutureDocTest.java
  157. :include: onComplete
  158. Ordering
  159. --------
  160. Since callbacks are executed in any order and potentially in parallel,
  161. it can be tricky at the times when you need sequential ordering of operations.
  162. But there's a solution! And it's name is ``andThen``, and it creates a new ``Future`` with
  163. the specified callback, a ``Future`` that will have the same result as the ``Future`` it's called on,
  164. which allows for ordering like in the following sample:
  165. .. includecode:: code/docs/future/FutureDocTest.java
  166. :include: and-then
  167. Auxiliary methods
  168. -----------------
  169. ``Future`` ``fallbackTo`` combines 2 Futures into a new ``Future``, and will hold the successful value of the second ``Future``
  170. if the first ``Future`` fails.
  171. .. includecode:: code/docs/future/FutureDocTest.java
  172. :include: fallback-to
  173. You can also combine two Futures into a new ``Future`` that will hold a tuple of the two Futures successful results,
  174. using the ``zip`` operation.
  175. .. includecode:: code/docs/future/FutureDocTest.java
  176. :include: zip
  177. Exceptions
  178. ----------
  179. Since the result of a ``Future`` is created concurrently to the rest of the program, exceptions must be handled differently.
  180. It doesn't matter if an ``UntypedActor`` or the dispatcher is completing the ``Future``, if an ``Exception`` is caught
  181. the ``Future`` will contain it instead of a valid result. If a ``Future`` does contain an ``Exception``,
  182. calling ``Await.result`` will cause it to be thrown again so it can be handled properly.
  183. It is also possible to handle an ``Exception`` by returning a different result.
  184. This is done with the ``recover`` method. For example:
  185. .. includecode:: code/docs/future/FutureDocTest.java
  186. :include: recover
  187. In this example, if the actor replied with a ``akka.actor.Status.Failure`` containing the ``ArithmeticException``,
  188. our ``Future`` would have a result of 0. The ``recover`` method works very similarly to the standard try/catch blocks,
  189. so multiple ``Exception``\s can be handled in this manner, and if an ``Exception`` is not handled this way
  190. it will behave as if we hadn't used the ``recover`` method.
  191. You can also use the ``recoverWith`` method, which has the same relationship to ``recover`` as ``flatMap`` has to ``map``,
  192. and is use like this:
  193. .. includecode:: code/docs/future/FutureDocTest.java
  194. :include: try-recover
  195. After
  196. -----
  197. ``akka.pattern.Patterns.after`` makes it easy to complete a ``Future`` with a value or exception after a timeout.
  198. .. includecode:: code/docs/future/FutureDocTest.java
  199. :include: imports8
  200. .. includecode:: code/docs/future/FutureDocTest.java
  201. :include: after