class: center, middle # Future & CompletionStage .byline[ *Will Billingsley, CC-BY* ] --- ## Why Futures? Sometimes we don't want to wait for a result * Long-running task in a UI framework * Network call to another computer * Waiting for user input --- ## Threads in Java ```java new Thread(() -> { // Do something }).start(); ``` --- ## Thread blocking example * Most UI toolkits only have one UI thread * If you do something long-running in an event-handler, it blocks the thread and freezes the UI --- ## A simple app ```java public class Main extends Application { volatile double h = 0; volatile double rot = 0; @Override public void start(Stage primaryStage) throws Exception{ Rectangle r = new Rectangle(200,200); Button b = new Button("Long task!"); VBox vBox = new VBox(r, b); Scene scene = new Scene(vBox); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } ``` This shows a black rectangle, sitting above a button --- ## Let's make it spin the rectangle ```java TimerTask timerTask = new TimerTask() { @Override public void run() { h = (h + 1) % 255; rot = (rot + 3) % 360; Platform.runLater(() -> { r.setFill(Color.hsb(h, 1, 1)); r.setRotate(rot); }); } }; Timer t = new Timer(); t.schedule(timerTask, 1000/60, 1000/60); ``` --- ## Now let's do something long when you press the button ```java b.setOnAction((evt) -> { try { Thread.sleep(10000); } catch (Exception ex) { // } }); ``` When we press the button, the rectangle stops spinning --- ## What's happening... * Our timer is still working (we can put in a println to check), because it is running on a different thread * But the *UI thread* is busy (sleeping) for 10 seconds, so can't repaint the screen or react to any more button presses --- ## Let's fix it ```java b.setOnAction((evt) -> { new Thread(() -> { try { Thread.sleep(10000); } catch (Exception ex) { // } }).start(); }); ``` Now the "long running task" happens on a different thread (not the UI thread) and doesn't block the UI --- ## Thread exhaustion  --- ## Communicating between threads Let's take another look at this code... ```java TimerTask timerTask = new TimerTask() { @Override public void run() { h = (h + 1) % 255; rot = (rot + 3) % 360; Platform.runLater(() -> { r.setFill(Color.hsb(h, 1, 1)); r.setRotate(rot); }); } }; Timer t = new Timer(); t.schedule(timerTask, 1000/60, 1000/60); ``` --- ## Communicating between threads In our Java code, the TimerTask runs on its own thread. But the instructions to update the rectangle have to be put *back on the UI thread* because they modify the UI state. ```java Platform.runLater(() -> { r.setFill(Color.hsb(h, 1, 1)); r.setRotate(rot); }); ``` This is possible because the UI thread has a queue of tasks, and goes back to check it regularly. ie, this communication isn't built into Threads, it's just that the code that is *running on the UI thread* was written to look in a queue for tasks to do. (Platform.runLater is a method from the javafx packages) --- ## An observation We've talked about concurrency in Java, but it's all been closely tied to *how concurrency is implemented*. It would be nice to be able to talk just about the tasks. And to be able to compose them as easily as we can compose functions. --- ## Futures `Future`s let us talk about *a computation that will complete at some point in the future*. * Suppose we have a box `[ ]` -- * It will receive a value `[ 7 ]` -- * But I don't know when `[ ? ]` -- *When the box has a value, print it out* --- ## Futures ```scala val myFuture:Future[Int] = longRunningTask() myFuture.onSuccess({ case x => println(x) }) ``` --- ## Java has Futures too... * Java has had a class called `Future` since Java 5... ... but it doesn't have the methods we want (onSuccess, etc) * Java 8 introduced `CompletionStage` --- ## CompletionStage > A stage of a possibly asynchronous computation, that performs an action or computes a value when another CompletionStage completes. A stage completes upon termination of its computation, but this may in turn trigger other dependent stages. ```java stage.thenApply(x -> square(x)) .thenAccept(x -> System.out.print(x)) .thenRun(() -> System.out.println()) ``` Roughly the same as the Scala version, but named differently --- ## CompletionStage in the sample code ```java public CompletionStage<Result> index() { return FutureConverters.toJava(ask(actorSetup.marshallActor, "Report!", 1000)) .thenApply(response -> ok(response.toString())); } ``` * Ask the marshall to report (returning a Scala Future) * Turn the Scala Future into a Java CompletionStage * when it completes, take its response and turn it into an `OK` response with the string content --- ## Promises How do we fill the box? For now, let's use a `Promise` ```scala val promise = Promise[Int] val future = promise.future // later promise.success(1) ``` "I *promise* at some point in the future I will put an `Int` into this box" --- ## Let's do a network request... Using the Play WS library, this would return a `Future[WSRequest]` ```scala val wsClient = AhcWSClient() val f = wsClient .url("http://google.com") .get() ``` It returns the Future ***immediately***. The future completes ***eventually*** (when the HTTP request succeeds). --- ## Let's do a network request... ```scala val wsClient = AhcWSClient() val f = wsClient .url("https://api.github.com/zen") .get() f.foreach({ req => println(req.body) }) println("This prints immediately") ``` will print "This prints immediately" before the request for a zen saying from GitHub has returned. --- ## Map We have a computation that will complete in the future. Maybe we want to do something with it. We can compose a function onto our future using `map`. ```scala val wsClient = AhcWSClient() val f = wsClient .url("https://api.github.com/zen") .map(_.body).map(_.toUpperCase) f.foreach({ req => println(req.body) }) println("This prints immediately") ``` -- *A computation that finishes in the future, with the result then made uppercase, is also a computation that finishes in the future* --- ## FlatMap * Suppose the next bit of processing is also asynchronous. * *Something that finishes in the future, and then doing something else that finishes in the future, produces something that finishes in the future* * So we should be able to chain two Futures together to get another Future --- ## Let's put our "trite saying" fetcher into a function ```scala def triteSaying():Future[String] = { wsClient .url("https://api.github.com/zen") .get() .map(_.body) } ``` --- ## Let's do two of them ```scala triteSaying() .andThen({ case x => println(x) }) .flatMap({ case x => triteSaying()}) .andThen({ case x => println(x) }) ``` --- ## Errors * In synchronous code, we are used to returning exceptions * When these occur, they propagate up the thread's call stack until they are caught * But in our concurrent scenario, that's a bit useless -- *we've already moved on*. So instead, failure is a possible state of a `Future` --- ## Error handling In an event-handling style (returns `Unit`): ```scala f.onFailure { case NotFoundException(ex) => /* ... */ } ``` In a composable computation style (returns a `Future`): ```scala f.recoverWith { case NotFoundException(ex) => Future.successful(...) } ``` --- ## Error handling in Java ```java completionStage.handle((value, exception) -> { System.out.println("oops!"); return null; }); ```