Advertisement
mitrakov

Scala: Future compositions

Feb 27th, 2018
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.53 KB | None | 0 0
  1. // 1. Let's try Future composition (suppose all the Futures are independent!)
  2. import java.time.LocalDateTime
  3. import scala.concurrent.ExecutionContext.Implicits.global
  4. import scala.concurrent.Future
  5. import scala.io.StdIn
  6. import scala.language.postfixOps
  7.  
  8. object Main extends App {
  9.   def print(x: Any): Unit = {Thread.sleep(50); println(s"${LocalDateTime.now()}: $x")}
  10.  
  11.   def f1 = Future {
  12.     print("Future 1 started")
  13.     Thread.sleep(3000)
  14.     print("Future 1 finished")
  15.     5
  16.   }
  17.  
  18.   def f2 = Future {
  19.     print("Future 2 started")
  20.     Thread.sleep(3000)
  21.     print("Future 2 finished")
  22.     true
  23.   }
  24.  
  25.   def f3 = Future {
  26.     print("Future 3 started")
  27.     Thread.sleep(3000)
  28.     print("Future 3 finished")
  29.     "Tommy"
  30.   }
  31.  
  32.   val result = for {
  33.     x <- f1
  34.     y <- f2
  35.     z <- f3
  36.   } yield (x, y, z)
  37.  
  38.   print("Press ENTER to finish")
  39.   StdIn.readLine()
  40.   print(s"result is $result")
  41. }
  42.  
  43.         // Output (note seconds!):
  44.         // 2018-02-27T22:24:33.867: Press ENTER to finish
  45.         // 2018-02-27T22:24:33.867: Future 1 started
  46.         // 2018-02-27T22:24:36.924: Future 1 finished
  47.         // 2018-02-27T22:24:36.975: Future 2 started
  48.         // 2018-02-27T22:24:40.025: Future 2 finished
  49.         // 2018-02-27T22:24:40.076: Future 3 started
  50.         // 2018-02-27T22:24:43.126: Future 3 finished
  51.  
  52.         // 2018-02-27T22:24:46.707: result is Future(Success((5,true,Tommy)))
  53.  
  54. // 2. Now let's do it simultaneously!
  55. val runF1 = f1 // start Future #1!
  56. val runF2 = f2 // start Future #2!
  57. val runF3 = f3 // start Future #3!
  58. print("Now we can use for-comprehension")
  59. val result = for {
  60.   x <- runF1
  61.   y <- runF2
  62.   z <- runF3
  63. } yield (x, y, z)
  64.  
  65.         // Output (note seconds!):
  66.         // 2018-02-27T22:27:03.395: Future 1 started
  67.         // 2018-02-27T22:27:03.395: Future 3 started
  68.         // 2018-02-27T22:27:03.395: Future 2 started
  69.         // 2018-02-27T22:27:03.395: Now we can use for-comprehension
  70.         // 2018-02-27T22:27:03.455: Press ENTER to finish
  71.         // 2018-02-27T22:27:06.452: Future 1 finished
  72.         // 2018-02-27T22:27:06.452: Future 2 finished
  73.         // 2018-02-27T22:27:06.452: Future 3 finished
  74.  
  75.         // 2018-02-27T22:27:07.949: result is Future(Success((5,true,Tommy)))
  76.  
  77. // 3. Bonus! If all the Futures return the same type (e.g. Int), we can use 'sequence'.
  78. // if the types are different, it still works, but casts to a most common type (e.g. to Any).
  79. object Main extends App {
  80.   def print(x: Any): Unit = {Thread.sleep(50); println(s"${LocalDateTime.now()}: $x")}
  81.  
  82.   def f1 = Future {
  83.     print("Future 1 started")
  84.     Thread.sleep(3000)
  85.     print("Future 1 finished")
  86.     5
  87.   }
  88.  
  89.   def f2 = Future {
  90.     print("Future 2 started")
  91.     Thread.sleep(3000)
  92.     print("Future 2 finished")
  93.     6
  94.   }
  95.  
  96.   def f3 = Future {
  97.     print("Future 3 started")
  98.     Thread.sleep(3000)
  99.     print("Future 3 finished")
  100.     7
  101.   }
  102.  
  103.   val result: Future[List[Int]] = Future.sequence(List(f1, f2, f3))
  104.  
  105.   print("Press ENTER to finish")
  106.   StdIn.readLine()
  107.   print(s"result is $result")
  108. }
  109.  
  110.         //Output:
  111.         //2018-02-27T22:28:27.663: Future 2 started
  112.         //2018-02-27T22:28:27.663: Future 1 started
  113.         //2018-02-27T22:28:27.663: Future 3 started
  114.         //2018-02-27T22:28:27.663: Press ENTER to finish
  115.         //2018-02-27T22:28:30.719: Future 2 finished
  116.         //2018-02-27T22:28:30.719: Future 1 finished
  117.         //2018-02-27T22:28:30.719: Future 3 finished
  118.  
  119.         //2018-02-27T22:28:31.665: result is Future(Success(List(5, 6, 7)))
  120.  
  121. // 3. Bonus #2! 'traverse' is more generic variant of 'sequence':
  122. object Main extends App {
  123.   def print(x: Any): Unit = {Thread.sleep(50); println(s"${LocalDateTime.now()}: $x")}
  124.  
  125.   def f(x: Int) = Future {
  126.     print("Future started")
  127.     Thread.sleep(3000)
  128.     print("Future finished")
  129.     x*x
  130.   }
  131.  
  132.   val result: Future[List[Int]] = Future.traverse(List(1, 2, 3, 4)) {t => f(t)}
  133.  
  134.   print("Press ENTER to finish")
  135.   StdIn.readLine()
  136.   print(s"result is $result")
  137. }
  138.  
  139.         //Output:
  140.         //2018-02-27T22:30:40.698: Future started
  141.         //2018-02-27T22:30:40.698: Future started
  142.         //2018-02-27T22:30:40.698: Future started
  143.         //2018-02-27T22:30:40.698: Press ENTER to finish
  144.         //2018-02-27T22:30:40.698: Future started
  145.         //2018-02-27T22:30:43.756: Future finished
  146.         //2018-02-27T22:30:43.756: Future finished
  147.         //2018-02-27T22:30:43.757: Future finished
  148.         //2018-02-27T22:30:43.758: Future finished
  149.  
  150.         //2018-02-27T22:30:45.072: result is Future(Success(List(1, 4, 9, 16)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement