46
ilJUG Java 8 Launch Event The Future of Futures (Apr 2014) Haim Yadid - Performize-IT

The Future of Futures - A Talk About Java 8 CompletableFutures

Embed Size (px)

DESCRIPTION

This talk was given during the Java 8 Launch Event of the Israeli Java User Group (ilJUG) It is talking about Java8 CompletableFuture

Citation preview

Page 1: The Future of Futures - A Talk About Java 8 CompletableFutures

ilJUG  Java  8  Launch  Event    The  Future  of  Futures  

(Apr  2014)  !

Haim Yadid - Performize-IT

Page 2: The Future of Futures - A Talk About Java 8 CompletableFutures

About  Me:  Haim  Yadid

•21 Years of SW development experience •Performance Expert •Consulting R&D Groups •Training: Java Performance Optimization •Organizing : ILJUG

Page 3: The Future of Futures - A Talk About Java 8 CompletableFutures

IL  JUG

•Israeli Java User Group •Reborn at 1/14 •Meetup : http://www.meetup.com/IL-JUG •G+: https://plus.google.com/u/0/communities/110138558454900054301

•Twitter: @il_jug

Page 4: The Future of Futures - A Talk About Java 8 CompletableFutures
Page 5: The Future of Futures - A Talk About Java 8 CompletableFutures

The  Beginning  of  Times

•Before J1.5 •Primitive life forms without Future •Threads •synchronization primitives •wait / notify •Most likely you will do it wrong

Page 6: The Future of Futures - A Talk About Java 8 CompletableFutures

Futures  Introduction

•j.u.c.Future •introduced in JDK 1.5 •jsr166 (Doug Lea) •Together with Executors •And many other concurrency constructs •Part of the java.util.concurrent

Page 7: The Future of Futures - A Talk About Java 8 CompletableFutures

What  is  a  Future

•A container for a result that will become available at a later time •Backed by a thread •May contain a Throwable if computation fails

Page 8: The Future of Futures - A Talk About Java 8 CompletableFutures

What  is  a  Future

•Future means asynchronous •Future does not mean non blocking •Future does not mean reactive

Page 9: The Future of Futures - A Talk About Java 8 CompletableFutures

The  ExecutorService

•Executor service is the container which handles a future •Has the threads which futures need. •Part of j.u.c (Executors.newXXX) •SingleThreadExecutor •FixedThreadPool •CachedThreadPool •ScheduledThreadPool

Page 10: The Future of Futures - A Talk About Java 8 CompletableFutures

Simplest  Example

ExecutorService e = Executors.newSingleThreadExecutor();! Future<Integer> future = e.submit( () -> {sleep(1000);return 42;} ) ; // do something useful ? System.out.println(future.get());

Lambda  expression  which  represents  a  Callable<Integer>

User

Task(Callable,  Runnable)

Future

Executor

Page 11: The Future of Futures - A Talk About Java 8 CompletableFutures

What  Else  Can  Be  Done?

•So we are blocked until future is finished •If it throw exception get will throw an exception •More that can be done: !

!

!

•And thats all !

future.cancel(false) ; // cancel future if not executed yet (in queue) future.cancel(true); // in addition interrupt the running task future.isCancelled(); // wether the future is cancelled. future.idDone() // whether the future is done.

Page 12: The Future of Futures - A Talk About Java 8 CompletableFutures

Futures  Pros

•Futures combined with Callables are cheaper than threads. •Easier to maintain. •Async

We  will  get  to  the  cons…

Page 13: The Future of Futures - A Talk About Java 8 CompletableFutures

Futures  Evolution  -­‐  Java  6

•Java 6 -jsr166x (CompletionService) •Separation of concerns

ExecutorService e = Executors.newFixedThreadPool(10);!CompletionService<Integer> completionService = new ExecutorCompletionService<>(e);! completionService.submit(() -> {sleep(1000); return 42;}) ;!Future<Integer> future = completionService.take();System.out.println(future.get()); // already completed…..

UserFuture

Executor ConsumerTask

Page 14: The Future of Futures - A Talk About Java 8 CompletableFutures

Futures  Evolution  -­‐  Java  7

•Java7 - jsr166y (Fork Join Pools) •Has a common pool •ForkJoinTask extends Future •Completion ?

ForkJoinTask<Integer> task = ForkJoinPool.commonPool(). submit( () -> { sleep(1000); System.out.printf("done"); }); System.out.println(task.get());

Page 15: The Future of Futures - A Talk About Java 8 CompletableFutures

complete()    a  Complete  mess

•With the method complete you can introduce a value before task competes. •But

ForkJoinTask<Integer> task = ForkJoinPool.commonPool(). submit(() -> { sleep(1000); return 42; }); ! sleep(10); task.complete(43); System.out.println(task.get()); task.complete(44); System.out.println(task.get()); sleep(2000); System.out.println(task.get());

43  

42  

44  

Page 16: The Future of Futures - A Talk About Java 8 CompletableFutures
Page 17: The Future of Futures - A Talk About Java 8 CompletableFutures

Nothing

•Dinosaurs are perfect •They are big •Powerful •State of the art

Nothing,  but  evolution  

Page 18: The Future of Futures - A Talk About Java 8 CompletableFutures

Alternatives

•Akka Futures/Scala Futures •Scala Promises •Twitter - Finnagle •Guava ListenableFuture •Groovy Dataflow concurrency (GPars)

Page 19: The Future of Futures - A Talk About Java 8 CompletableFutures

Proper  Completion

•A correct way to complete a future. •Once a future is completed it immutable •It is IMPORTANT

Page 20: The Future of Futures - A Talk About Java 8 CompletableFutures

Data-­‐flow  Concurrency

•If we have variables that can be written to once •We have deterministic behaviour! •Run it a million times it will still work the same!!!

Page 21: The Future of Futures - A Talk About Java 8 CompletableFutures

Composition

•Looking for websites that will interest a group of people

Get  Profile  On  linked  in  

user  1

Find  intersection  of  skills

Get  Profile  On  linked  in  

user  1

Get  Profile  On  linked  in  

user  n

search  on  google

Send  mail  with  group  recommendation

…….

Page 22: The Future of Futures - A Talk About Java 8 CompletableFutures
Page 23: The Future of Futures - A Talk About Java 8 CompletableFutures

 CompletableFuture  Is

•A container for a result that will become available at a later time •Backed by thread •May contain a Throwable if computation failed

Page 24: The Future of Futures - A Talk About Java 8 CompletableFutures

CompletableFuture  Is

•Means asynchronous •Does not mean non blocking •Does not mean reactive

Page 25: The Future of Futures - A Talk About Java 8 CompletableFutures

Is  Completable

•Is completed when completed! •The result can be set once. •Either by the task itself •Or from outside.

Page 26: The Future of Futures - A Talk About Java 8 CompletableFutures

Is  Composable

•Composable •Lambda expression friendly •More functional in it’s nature

Page 27: The Future of Futures - A Talk About Java 8 CompletableFutures

CompletableFuture  Creation

•supplyAsync •runAsync

import  java.util.concurrent.CompletableFuture;import  static  java.util.concurrent.CompletableFuture.*;

             CompletableFuture<Integer>  f  =  supplyAsync(                                  ()  -­‐>  {sleep(10000);return  42;}                );                  f.join();

Runs  on  ForkJoinPool.commonPool;  You  can  supply  an  executor  if  you  wantjoin  is  the  same  as  get  but  throws  an  

unchecked  exception  (hip  hip  hurray)

Page 28: The Future of Futures - A Talk About Java 8 CompletableFutures

Construction

•new CompletableFuture(); •use complete(r) to complete it •use completeExceptionally(t) to complete with an exception

 CompletableFuture<Integer>  a=  new  CompletableFuture<>();

 a.complete(5);  a.completeExceptionally(new  IndexOutOfBoundsException());  

Page 29: The Future of Futures - A Talk About Java 8 CompletableFutures

CompletableFuture

•Implements CompletableStage •A large set of methods (~60 •Every method is multiplied by three •XXXX(….) •XXXXAsync(…) •XXXX(….,Executor x)

Page 30: The Future of Futures - A Talk About Java 8 CompletableFutures

Future  -­‐>  CompletableFuture

•Not really possible (Cleanly)

               Future<Integer>  future  =  ForkJoinPool.commonPool().submit(   ()  -­‐>  {sleep(4000);return  42;}                );!                CompletableFuture<Integer>  brighterFuture  =  supplyAsync(()  -­‐>  {                        try  {                                return  future.get();                        }  catch  (Exception  e1)  {                                throw  new  RuntimeException(e1);                        }                });                System.out.println(brighterFuture.get());

Nasty  Exception  handling  

Requires  another  thread….

Page 31: The Future of Futures - A Talk About Java 8 CompletableFutures

!

Page 32: The Future of Futures - A Talk About Java 8 CompletableFutures

thenApply

•Apply another action when result is available            

CompletableFuture<Integer>  f  =  supplyAsync(                        ()  -­‐>  {sleep(10000);return  42;});!CompletableFuture<Integer>  f2  =    f.thenApply((r)  -­‐>  r*r);

CompletableFuture<Integer>  f2  =    f.thenApplyAsync((r)  -­‐>  r*r);

CompletableFuture<Integer>  f2  =    f.thenApplyAsync((r)  -­‐>  r*r,                                                myLowPriorityExecutor);

Page 33: The Future of Futures - A Talk About Java 8 CompletableFutures

Handling  Exceptions

•exceptionally()

CompletableFuture<Integer>  f  =  supplyAsync(                                ()  -­‐>  {sleep(10000);                                if  (true)  throw  new  RuntimeException();                                  return  42;});!CompletableFuture<Integer>  f2  =                          f.exceptionally((t)-­‐>  2).                            thenApply((r)  -­‐>  r*r);System.out.println(f2.get());

Page 34: The Future of Futures - A Talk About Java 8 CompletableFutures

The  General  Case

•handle() - gets result and throwable manipulates them •whenComplete() - does something, pass result through

CompletableFuture<Integer>  f2  =  f.handle(                      (res,throwable)  -­‐>  (throwable==null)?  res*res  :  2);  !CompletableFuture<Integer>  f3  =  f.whenComplete(                              (res,  throwable)  -­‐>  {System.out.println("done");});

Page 35: The Future of Futures - A Talk About Java 8 CompletableFutures

Composition

•thenCompose() •Performs another stage upon completion •On failure stage will not be performed

               CompletableFuture<Integer>  f1  =  supplyAsync(                                ()  -­‐>  {sleep(2100);return  42;});!                CompletableFuture<Integer>  f2  =  f1.thenCompose(                                (v)  -­‐>  supplyAsync(()  -­‐>  {sleep(2100);return  v+42;}))    ;                System.out.println(f2.get());

Page 36: The Future of Futures - A Talk About Java 8 CompletableFutures

Combiners

•thenCombine() take both results and apply a function on them •thenAcceptBoth() - guess

               CompletableFuture<Integer>  f1  =  supplyAsync(                                ()  -­‐>  {sleep(2100);return  42;});                CompletableFuture<Integer>  f2  =  supplyAsync(                                ()  -­‐>  {sleep(2100);return  55;});!                CompletableFuture<Integer>  f3  =  f1.thenCombine(f2,                                (r1,r2)  -­‐>  r1+r2)    ;                  CompletableFuture<Void>  f4  =  f1.thenAcceptBoth(f2,                                (r1,  r2)  -­‐>  System.out.println(r1  +  r2))    ;                System.out.println(f3.get());

Page 37: The Future of Futures - A Talk About Java 8 CompletableFutures

Either…

•thenApplyEither() take fastest result use it. Discard the second one •If exception is thrown behaviour is not predictable •Use case: parse fastest server result

               CompletableFuture<Integer>  f1  =  supplyAsync(                                ()  -­‐>  {sleep(2300);return  42;});                CompletableFuture<Integer>  f2  =  supplyAsync(                                ()  -­‐>  {sleep(2200);return  43;});!                CompletableFuture<Integer>  f3  =  f1.applyToEither(f2,(r)  -­‐>  r  *  r);

Page 38: The Future of Futures - A Talk About Java 8 CompletableFutures

A  Better  Either

•Hold down exceptions letting other futures a chance to complete

 static<T>  CompletableFuture<T>  holdDownExceptionally(CompletableFuture<T>f,  CountDownLatch  latch)  {                  return  f.exceptionally((t)  -­‐>  {                                try  {                                        latch.countDown();latch.await();                                }  catch  (Exception  e)  {                                        throw  new  RuntimeException(t);                                }                                throw  new  RuntimeException(t);                          }).                            thenApply((r)  -­‐>  {latch.countDown();latch.countDown();return  r;});        }

Page 39: The Future of Futures - A Talk About Java 8 CompletableFutures

A  Better  Either  cont

static  <T,U>  CompletableFuture<U>myApplytoEither(CompletableFuture<T>  f1,                                                                CompletableFuture<T>  f2,                                                              Function<?  super  T,  U>  fn)    {                  CountDownLatch  latch  =  new  CountDownLatch(2);                  CompletableFuture<T>  f1be  =  holdDownExceptionally(f1,latch);                CompletableFuture<T>  f2be  =  holdDownExceptionally(f2,latch);                  return  f1be.applyToEither(f2be,fn);}

Page 40: The Future of Futures - A Talk About Java 8 CompletableFutures

How  Many?

•A completable future may have more than one dependents •Use getNumberOfDependents to get an estimate

CompletableFuture<Integer>  f  =  supplyAsync(                        ()  -­‐>  {sleep(10000);return  42;});!CompletableFuture<Integer>  f2  =    f.thenApply((r)  -­‐>  r*r);CompletableFuture<Integer>  f3  =    f.thenApply((r)  -­‐>  r*r*r);CompletableFuture<Integer>  f4  =    f.thenApply((r)  -­‐>  r*r*r*r);!f.getNumberOfDependents();      //  returns  3

Page 41: The Future of Futures - A Talk About Java 8 CompletableFutures

Helper  Static  Functions

•allOf(CompletableFuture<?>... cfs) •no value returned

•anyOf(CompletableFuture<?>... cfs) •object retured

Page 42: The Future of Futures - A Talk About Java 8 CompletableFutures

NIO  Non  blocking  IO

•Selectors •dispatchers •Reactor pattern •There is no support out of the box for CompletableFutures in NIO

Page 43: The Future of Futures - A Talk About Java 8 CompletableFutures

What  about  J7  NIO2

•AsynchronousFileChannel •AsynchronousServerSocketChannel •Are using futures •Not adapted for completable futures.

AsynchronousFileChannel  afc  =                  AsynchronousFileChannel.open(Paths.get(“Video.avi"),                                StandardOpenOption.READ)      ;  ByteBuffer  r  =  ByteBuffer.allocate(500*1024*1024)  ;  Future<Integer>  a  =  afc.read(r,10*1024*1024);      //do  something  useful  while  waiting    a.get();      

Page 44: The Future of Futures - A Talk About Java 8 CompletableFutures

Further  Info

•All examples can be found in github •https://github.com/lifey/compfut.git •Concurrency Interest Mailing List •Java Concurrency in Practice(Brian Goatz) •http://www.slideshare.net/kojilin/completable-future

Page 45: The Future of Futures - A Talk About Java 8 CompletableFutures
Page 46: The Future of Futures - A Talk About Java 8 CompletableFutures

Thanks + Q&A + Contact Me

© Copyright Performize-IT LTD.

http://il.linkedin.com/in/haimyadid

[email protected]

www.performize-it.com

blog.performize-it.com

https://github.com/lifey

@lifeyx