What is Advanced Excel and what are some best practices for designing and cre...
The Future of Futures - A Talk About Java 8 CompletableFutures
1. ilJUG
Java
8
Launch
Event
The
Future
of
Futures
(Apr
2014)
!
Haim Yadid - Performize-IT
2. About
Me:
Haim
Yadid
•21 Years of SW development experience
•Performance Expert
•Consulting R&D Groups
•Training: Java Performance Optimization
•Organizing : ILJUG
3. 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
4.
5. The
Beginning
of
Times
•Before J1.5
•Primitive life forms without Future
•Threads
•synchronization primitives
•wait / notify
•Most likely you will do it wrong
7. 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
8. What
is
a
Future
•Future means asynchronous
•Future does not mean non blocking
•Future does not mean reactive
9. 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
10. 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
11. 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.
12. Futures
Pros
•Futures combined with Callables are
cheaper than threads.
•Easier to maintain.
•Async
We
will
get
to
the
cons…
19. Proper
Completion
•A correct way to complete a future.
•Once a future is completed it immutable
•It is IMPORTANT
20. 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!!!
21. 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
…….
22.
23. 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
28. 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());
32. 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);
33. 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());
34. 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");});
35. 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());
36. 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());
37. 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);
38. 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;});
}
39. 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);
}
40. 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
42. NIO
Non
blocking
IO
•Selectors
•dispatchers
•Reactor pattern
•There is no support out of the box for
CompletableFutures in NIO
43. 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();
44. 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