think async in java 8
TRANSCRIPT
Think Asyncin Java 8
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Dmitry Alexandrov
2
Principal expert developer in T-System10 years in Java enterpriseBulgarian JUG co-leadConference [email protected]@t-systems.com
Plan for today: rethink the way we use system resources
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Let’s try to understand the word:
Asynchronous
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• A form of computer control timing
protocol in which a specific operation begins after receiving a signal
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• A form of computer control timing
protocol in which a specific operation begins after receiving a signal
• Not going at the same rate or exactly together with something else.
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• In simple words:– Start the task somewhere else
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• In simple words:– Start the task somewhere else– Notify me when its ready and I’ll process
the result
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• In simple words:– Start the task somewhere else– Notify me when its ready and I’ll process
the result–… in terms of Java: start a new thread,
do something there, somehow get the result
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• … by why?
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• … by why?– It can be really faster
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Asynchronous• … by why?– It can be really faster– Because its non-blocking
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
That class…• To get to the right understanding
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
That class…• To get to the right understanding• We need to have a look at it from
some different perspectives
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
That class…• To get to the right understanding• We need to have a look at it from
some different perspectives • Because several technologies
actually made it happen
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
But first: Evolution of
multithreading in Java
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
How it all began: Threads
public class HelloRunnable implements Runnable { public void run() { //get some value and store it a shared variable }
public static void main(String[] args) { (new Thread(new HelloRunnable())).start(); }}
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
How it all began: Threads
Or…
public class HelloThread extends Thread { public void run() { //get some value and store it a shared variable }
public static void main(String[] args) { (new HelloThread()).start(); }}
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
But then: Executor Services
And then Concurrency API has been introduced back in 2004 with the release of Java 5
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
But then: Executor Services
So that we no longer had to think at such a low level…
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() { public void run() { System.out.println("Asynchronous task"); }});
executorService.shutdown();
dalexandrov.net | @bercut2000 | jug.bg | @bgjugCasablanca | November 1-3, 2016 | @DevoxxMA
And with it came the…Future
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Future – a primitive for creating multithreaded
applications
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Actually that’s not something too new:
A somewhat similar concept future was introduced in 1977 in a paper by Henry Baker and Carl Hewitt.
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
a function:getASpecialInt()
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
We have to put this work (in a container)
Future
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Putting work in a containerPromise
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Promise• A function to put a work in a
“container”
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Promise• A function to put a work in a
“container”
• This is not something new too..
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
The term promise was proposed in 1976 by Daniel P. Friedman and David Wise,[1] and Peter
Hibbard called it eventual..
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
FutureFuture:
- observe container and make callbacks- transform resulting value inside the
container
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Conceptually we should NOT remove value outside of the container
Future
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Future in Java
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
FutureReally hided lots of the intrinsic of the multithreading
ExecutorService executor = Executors.newFixedThreadPool(1);Future<Integer> future = executor.submit(task);
System.out.println("future done? " + future.isDone());
Integer result = future.get();
System.out.println("future done? " + future.isDone());System.out.print("result: " + result);
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
FutureThe interface was really simplistic:
• isDone()• Get() • Get(..timeout)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
FutureThe interface was really simplistic:
• isDone()• Get() • Get(..timeout)
Are blocking..
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
FutureThe interface was really simplistic:
• isDone()• Get() • Get(..timeout)
So we are breaking the law!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Future
Submit()
get()
Result ready
main Thread 1
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Future
Submit()
get()
Result ready
main Thread 1
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Future
Submit()
get()
Result ready
main Thread 1
Do something Useful here
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
From the definition:we don’t have to wait or
block
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
We have to make callbacks
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CallbacksImagine:public static void processResultAsync(Supplier<List<Long>> supplier, ExecutorService executor, Consumer<List<Long>> onSuccess, Consumer<Throwable> onFail) { executor.submit(() -> { try { List<Long> lines = supplier.get(); onSuccess.accept(lines); } catch (Exception e) { onFail.accept(e); } });
}
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CallbacksAnd now how we use it:final ExecutorService executor = Executors.newSingleThreadExecutor();
processResultAsync( AsyncCallbacks::getFibunacci, executor, System.out::println, Throwable::printStackTrace);
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CallbacksBut the logic becomes really thick if get into callbacks:final ExecutorService executor = Executors.newSingleThreadExecutor();
processResultAsync( AsyncCallbacks::getPrime, executor, r -> processResultAsync( AsyncCallbacks::getFibunacci, executor, t-> System.out.println(r.stream() .filter(t::contains) .collect(Collectors.toList())), Throwable::printStackTrace ), Throwable::printStackTrace);
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?• JavaScript/Node.js
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?• JavaScript/Node.js• Non-blocking API, event driven model
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?• JavaScript/Node.js• Non-blocking API, event driven model• Callbacks!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?• JavaScript/Node.js• Non-blocking API, event driven model• Callbacks! That’s so cool!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?• JavaScript/Node.js• Non-blocking API, event driven model• Callbacks! That’s so cool!• But in reality…
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
they did it elsewhere?
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Say “callback” to a JavaScript developer and he will start
crying instantaneously!
Venkat Subramaniam
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
How they did it elsewhere
• JavaScript/Node.js• Non-blocking API, event driven model• Callbacks! That’s so cool!• But in reality… not cool!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
How they did it elsewhere
• JavaScript/Node.js• Non-blocking API, event driven model• Callbacks! That’s so cool!• But in reality… not cool!• But promises kinda fixed that.
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
How they did it elsewhere
So instead of:
step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // Do something with value4 }); }); });});
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
How they did it elsewhere
This look oh so much better:
Q.fcall(promisedStep1) .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) {
// Do something with value4 }) .catch(function (error) {
// Handle any error from all above steps }) .done();
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But not only in Javascript • Guava ListenableFuture addressed
the same issue
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But not only in Javascript • Guava ListenableFuture addressed
the same issue
• But it was complicated..
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
GuavaListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS));
ListenableFuture<String> listenableFuture = executor.submit(asyncTask);
Futures.addCallback(listenableFuture, new FutureCallback<String>() { public void onSuccess(String result) { doMoreWithTheResultImmediately(result); }
public void onFailure(Throwable thrown) { handleFailure(thrown); }});
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Guava
Futures.transform()…
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Let’s now put it all together!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
How to achieve asynchronicity in Java 8
*without additional libraries
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
It’s done by:CompletableFuture<T>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture<T>• Core library since Java 8
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture<T><<Interface>>
Future<T>
CompletableFuture<?>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture<T><<Interface>>
Future<T>
<<Interface>>
CompletionStage<T>
CompletableFuture<?>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture<T><<Interface>>
Future<T>
<<Interface>>
CompletionStage<T>
CompletableFuture<?>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture<T>• Core library since Java 8• Implements Future<T>• Implements CompletionStage<T>
– Composition element– Function resolution– Link through results– Transformation methods– toCompletableFuture()
• Async operations
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Foundation
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
1. Lambdas & Method ref.
• No more explicit Callables or Runnables
• No more ugly anonymous classes
• Just use Lambdas and Method references
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
2. ForkJoinThe ForkJoinPool (since JDK7) is an ideal helper for async programs
• Cares for cache corruption• Knows better when and where a task should run• Optimized for tasks creating new tasks• Avoid changing threads until workload is significant
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Casablanca | November 1-3, 2016 | @DevoxxMA
Thread 1
QueueTask1
Task2
Task3
Task8
Task9
Processor
Thread 2
Queue
Processor
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Thread 1
Queue
Processor
Thread 2
Queue
ProcessorTask1
Task2
Task3
Task8
Task9
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Thread 1
Queue
Processor
Thread 2
Queue
ProcessorTask1
Task2
Task3
Task8
Task9
Work stealing
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Back to the CompletableFuture
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: create
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: create
• CompletableFuture() cf =new
CompletableFuture();
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: create
• CompletableFuture<U>::supplyAsync(Supplier<U> supplier)
• CompletableFuture<U>::runAsync(Runnable runnable)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: create• CompletableFuture<U>::supplyAsync(Supplier<U
> supplier[, Executor executor])
• CompletableFuture<U>::runAsync(Runnable runnable[, Executor executor])
• ForkJoin.commonPool() by default
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: terminal
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: completeUnlike the Future<?>:
• CompletableFuture()::– complete(T value)– completeExceptionally(Throwable e)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: terminal• Can be completed only once!
• Can be run async but does not exclude blocking!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: terminal• CompletableFuture<Void>::thenAccept(Consumer
<T> c)
• CompletableFuture<Void>::thenRun(Runnable action)
• Async versions
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Methods: transform
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Remember this?
Methods: transform• CompletableFuture<U>::thenApply(Function<T,U
> fn)– Done in the same thread
• CompletableFuture<U>::thenApplyAsync(Function<T,U> fn, [Executor executor])
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
So if we get back to asyncWe just get the Prime method as it is:
public static List<Long> getPrimes() { List<Long> found = new ArrayList<Long>(); …. return found;}
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
So if we get back to asyncAnd just write one single line:
CompletableFuture.supplyAsync(AsyncCallbacks::getPrime) .thenAccept(System.out::println);
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Lets dive deeper
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Composition
CF<T> CF<U>
Casablanca | November 1-3, 2016 | @DevoxxMA
Transform smart
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompositionBut if we want both Futures to be completed in sequence:
• CompletableFuture<U>:: thenCompose(Function<T,CompletableFuture<U>> fn)
• CompletableFuture<U>:: thenComposeAsync(Function<T,CompletableFuture<U>> fn)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompositionBut if we want both Futures to be completed in sequence :
• CompletableFuture<U>:: thenCompose(Function<T,CompletableFuture<U>> fn)
• CompletableFuture<U>:: thenComposeAsync(Function<T,CompletableFuture<U>> fn)
.. to avoid: CompletableFuture<CompletableFuture<T>>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompositionBut if we want both Futures to be completed:
• CompletableFuture<U>:: thenCompose(Function<T,CompletableFuture<U>> fn)
• CompletableFuture<U>:: thenComposeAsync(Function<T,CompletableFuture<U>> fn)
.. to avoid: CompletableFuture<CompletableFuture<T>>
.. just like flatMap
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
And we getCompletableFuture<String> FilesUtils.readFileAsync(Path path)
CompletableFuture.supplyAsync(FilesUtils.readFileAsync(“…”)) .thenComposeAsync(content->processContent(content)) .thenAccept(System.out::println);
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/Reduce
Step
Next step
Step
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CombinationSo if the previous step returns Future<T>:
• CompletableFuture<V>:: thenCombine(CompletionStage<U> other, BiFunction<T,U,V> fn)
• CompletableFuture<V>:: thenCombineAsync(CompletionStage<U> other, BiFunction<T,U,V> fn)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combination• Just imagine how that would be with just Futures:
Future<List<Integer>> primesFuture = getPrimes();Future<List<Integer>> fibunacciFuture = getFibunacci();
...List<Integer> primes = primesFuture.get();List<Integer> fibunaccis= fibunacciFuture.get();// intersect
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/ReduceAnd we don’t want further processing:
• CompletableFuture<Void>:: thenAcceptBoth(CompletableFuture<U> other, BiConsumer<T,U> block)
• CompletableFuture<Void>::runAfterBoth(CompletableFuture<?> other, Runnable action)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/ReduceOr we want just the first available result:
• CompletableFuture<Void>:: acceptEither(CompletableFuture<T> other, Consumer<T> block)
• CompletableFuture<Void>:: runAfterEither(CompletableFuture<?> other, Runnable action)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/ReduceOr we want just the first available result:
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/ReduceOr we want just the first available result:
• But what happens to the second one?
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Combine/ReduceOr we want just the first available result:
• But what happens to the second one?
• So handle with care!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg |
@bgjug
Combine/ReduceOr we want just the first available result:
• But what happens to the second one?
• So handle with care!
• getNumberOfDependents()Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg |
@bgjug
Combine/Reduce• CompletableFuture<U>::
applyToEither(CompletableFuture<? extends T> other, Function<? super T,U> fn)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Multiple futures• CompletableFuture<Void>
allOf(CompletableFuture<?>... cfs)
• CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Multiple futures• CompletableFuture<Void>
allOf(CompletableFuture<?>... cfs)
• CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Exceptions
Handle Exception
IOException
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Exceptions• CompletableFuture<T>::exceptionally(Function<
Throwable,T> fn)
• CompletableFuture<Void>::handle(BiFunction<T,Throwable,U> fn)
• The exception is passed through the chainCasablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg |
@bgjug
ExceptionsLooks really safe:
CompletableFuture<Integer> safe = future.handle((val, ex) -> { if (val != null) { return Long.valueOf(val); } else { log.warn("Huston, we a have problem!", ex); return -1; }});
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Exceptions
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CompletableFuture.supplyAsync(FilesUtils.readFileAsync(“…”)) .thenComposeAsync(content->processContent(content)) .thenAccept(System.out::println) .exceptionally(Throwable::printStackTrace);
The API• You have probably noticed
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
The API• You have probably noticed • Unlike the Future<T>
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
The API• You have probably noticed • Unlike the Future<T>• The API is really BIG
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
The API• You have probably noticed • Unlike the Future<T>• The API is really BIG• Mostly fits the pattern:
<function>[Async](param,[Executer])
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
The API• You have probably noticed • Unlike the Future<T>• The API is really BIG• Mostly fits the pattern:
<function>[Async](param,[Executer])
Casablanca | November 1-3, 2016 | @DevoxxMA
>60 methods!!!
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CF for async• Organize the work as a chain/flow of events/tasks– Do this then that (chaining)– Do this and/or that (joining)– Do this on failure (recovering)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
CF for async• When we program asynchronously we usually
think in terms of workflows, events and tasksQuery
“Primes”
Query “Fibs”
Gather perf data
Gather statistics
Return response
Log data
Handle Exception
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
We have some (not so) bad heredity…
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Get• T get() throws InterruptedException, ExecutionException
• T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException
• T getNow(T valueIfAbcent)
• T join() throws CancellationException, CompletionException
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Get• T get() throws InterruptedException, ExecutionException
• T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException
• T getNow(T valueIfAbcent)
• T join() throws CancellationException, CompletionException
• T obtrudeValue() never ever use that!!!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
So have in mind:Imagine:
@GET@Path("intersection")public String getIntersection() throws ExecutionException, InterruptedException { CompletableFuture<List<Long>> fib = new FibunacciFuture().getFibunacci(50L); CompletableFuture<List<Long>> primes = new PrimeFuture().getPrime(10000L); CompletableFuture<List<Long>> intersection = fib.thenCombineAsync(primes, (a, b) ->
a.stream() .filter(b::contains) .collect(Collectors.toList())); return intersection.thenApply(List::toString).get();}
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
So have in mind:Imagine:
@GET@Path("intersection")public String getIntersection() throws ExecutionException, InterruptedException { CompletableFuture<List<Long>> fib = new FibunacciFuture().getFibunacci(50L); CompletableFuture<List<Long>> primes = new PrimeFuture().getPrime(10000L); CompletableFuture<List<Long>> intersection = fib.thenCombineAsync(primes, (a, b) ->
a.stream() .filter(b::contains) .collect(Collectors.toList())); return intersection.thenApply(List::toString).get();}
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
!Get()
“Prime”
Result ready
main Thread 1 Thread 2
Result ready
“Fibunacci”
Result ready
GET
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Should be supported all over
@GET@Path("intersectionAsync")public void getIntersectionAsync(@Suspended AsyncResponse response) { CompletableFuture<List<Long>> fib = new FibunacciFuture().getFibunacci(50L); CompletableFuture<List<Long>> primes = new PrimeFuture().getPrime(10000L); CompletableFuture<List<Long>> intersection = fib.thenCombineAsync(primes, (a, b) -> a.stream() .filter(b::contains) .collect(Collectors.toList()));
intersection.thenApplyAsync(List::toString).thenApplyAsync(response::resume).exceptionally(e->response.resume(e.getLocalizedMessage()));
response.setTimeout(10, TimeUnit.SECONDS); response.setTimeoutHandler(e->response.resume(new TimeoutException()));}
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Async everywhere
Casablanca | November 1-3, 2016 | @DevoxxMA
“Prime”
Result ready
main Thread 1 Thread 2
Result ready
“Fibunacci”
Both results ready
GET
dalexandrov.net | @bercut2000 | jug.bg | @bgjug
REACTIVE
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
REACTIVE is the new CLOUD
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
If you program reactively:
• You are the master of the Universe• Your salary doubles every time you
say this word• You are the star of the Java geek
parties
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
If you program reactively:
• You are the master of the Universe• Your salary doubles every time you
say this word• You are the star of the Java geek
parties• … until serverless came out
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But lets be honest• Actually, there is nothing so much
new
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But lets be honest• Actually, there is nothing so much
new• Remember the Observable Pattern?
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But lets be honest• Actually, there is nothing so much
new• Remember the Observable Pattern?• The key word is Asynchronous
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
But lets be honest• Actually, there is nothing so much
new• Remember the Observable Pattern?• The key word is Asynchronous• Java 8 supports now the pattern
really niceCasablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg |
@bgjug
And of course…
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Reactive
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
And what a good Reactive is
• Avoid blocking threads– Optimize the CPU usage
• Avoid changing threads– Optimize cache usage
• Avoid crippling failures– Failure of one task should be isolated and
handled elegantlyCasablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg |
@bgjug
Looks really nice• All benefits of async execution!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Looks really nice• All benefits of async execution!
• Fits well to the reactive pattern!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Looks really nice• All benefits of async execution!
• Fits well to the reactive pattern!
• Comes out of the box!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Looks really nice• All benefits of async execution!
• Fits well to the reactive pattern!
• Comes out of the box!
• Handle with care)
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
That’s all folks!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Any questions?
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Thank you!Merci beaucoup!
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug
Some more to read• http://
www.nurkiewicz.com/2013/05/java-8-definitive-guide-to.html
• https://habrahabr.ru/post/213319/
• https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
Casablanca | November 1-3, 2016 | @DevoxxMA dalexandrov.net | @bercut2000 | jug.bg | @bgjug