Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java 8 concurrency abstractions

3,852 views

Published on

Compares CompletableFutures with Classical Futures
and compares StampedLocks with ReadWriteLocks

Published in: Engineering
  • Be the first to comment

Java 8 concurrency abstractions

  1. 1. Java 8 Concurrency Abstractions -Exploring Java 8 concurrency abstractions -Comparing against Java 7 concurrency abstractions
  2. 2. Agenda 1. Overview of concurrency libraries added in JDK8 2. Asynchronous result processing 3. CompletableFuture (Vs classical Future) 4. StampedLock (Vs ReadWriteLock) ? Pre-requisites: Assumes Lambda, Method Ref,. Functional Interfaces (Supplier, Consumer, Function etc)
  3. 3. Myself • GlobalLogic India Ltd, Bangalore • Concurrency Enthusiast (Golang, Java) • Servlet 4.0 Spec (JSR 369), JavaEE8 • JavaCodeGeeks • Dzone
  4. 4. 1. Concurrency Overview – Adders And Accumulators – New Methods to ConcurrentHashMap – Common Pool
  5. 5. Asynchronous Result Processing 1. Overview of concurrency libraries added in JDK8 2. Asynchronous result processing 3. CompletableFuture (Vs classical Future) 4. StampedLock (Vs ReadWriteLock)
  6. 6. Asynchronous Result Processing – Synchronous – Not Synchronous, Asynchronous [Java 5] – Asynchronous and Reactive [Java 8] Client Server Request Server Proc... Client Blocked Response Synchronous Client Server Request Server Proc... Ctrl ret. immed Asynchronous Client polls - X Client polls - Y Response Client Server Request Server Proc... Response Push Ctrl ret. immed Asynchronous + Reactive
  7. 7. Agenda 1. Overview of concurrency libraries added in JDK8 2. Asynchronous result processing 3. CompletableFuture (Vs classical Future) 4. StampedLock (Vs ReadWriteLock)
  8. 8. Classical Future • An interface in java.util.concurrent pkg • FutureTask is the concrete implementation • Represents the result of an async processing. • Utility Methods with the interface: – isDone() – isCancelled() – cancel(boolean mayInterruptIfRunning) • Lets see it in action!
  9. 9. Classical Future continued 3 • Future programming model: ExecutorService pool = ... Future<Double> bankBalance=pool.submit(()->{ Thread.sleep(5000L);//sim processing time return bankBalance; }); try{ double balance = bankBalance.get(); //blocking call }catch(InterruptedException ignore){} • Work around: – May spin around and check with isDone() or isCancelled(); – Use CompletableFuture!
  10. 10. CompletableFuture • A class in java.util.concurrent package • Implements CompletionStage and Future interfaces (both in java.util.concurrent pkgs) • Since CompletableFuture implements Future, it can be used classically – blockingly! • CompletionStage is the interface which provides all the reactive constructs; fat interface
  11. 11. CompletableFuture Reactive Usage • CompletableFuture Programming Model. • Get a CompletableFuture instance: – Static Factory • CompletableFuture.supplyAsync(Supplier) //one variant • CompletableFuture<Double>bankBalanceFut = CompletableFuture.supplyAsync(()->{ return getBankBalance(); //long running task }) //args Supplier instance. • Wire reactions: • bankBalanceFut.thenAccept((balance)->{ //three variants; System.out.println(“Available balance: ”+balance) }) //args Consumer inst. • Lets try this!
  12. 12. supplyAsync(...) Variants • publicstatic <U> CompletableFuture<U> supplyAsync(Sup plier<U> supplier) – Uses ForkJoinPool.commonPool(); • publicstatic <U> CompletableFuture<U> supplyAsync(Sup plier<U> supplier, Executor executor) – Uses the passed into Executor as the thread pool • supplyAsync’s counterpart – runAsync(...) – Takes Runnable instead of Supplier – Returns CompletableFuture<Void> – Calling get() would return null
  13. 13. thenAccept(...) Variants • public CompletableFuture<Void> thenAccept(Consumer<? super T> action) • public CompletableFuture<Void> thenAcceptAsync(Consumer <? super T> action) • public CompletableFuture<Void> thenAcceptAsync(Consumer <? super T> action, Executor executor)
  14. 14. More into piping Reactions • Fluent API helps piping reactions. • supplyAsync(Supplier) .whenComplete(BiConsumer)//res, err .thenApply(Function) .thenAccept(Consumer) .thenRun(Runnable)
  15. 15. Other Important Piping APIs - 1 • Composition: public <U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn) (This) CompletionStage<U> Function(? super T, ? extends CompletionStage<U>) CompletionStage<T>
  16. 16. Other Important Piping APIs - 2 • Combination: public <U,V> CompletableFuture<V> thenCombine(Completio nStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn) (This) CompletionStage <U> (Other) CompletionStage <V> BiFunction(? super T, ? Super U, ? extends V) CompletionStage <T>
  17. 17. How we leveraged the power of CompletableFuture • Use Case #1 (Remote Serivces) – Two remote services. – Both replicate service – We needed anyone to respond; faster! (acceptEither) – Lets simulate what we did! – Can be extended easily to any number of services! • public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
  18. 18. How we leveraged the power of CompletableFuture - 2 • Use Case #2 (update UI after File FTP completes) – Application UI uploads file; not on UI thread; – UI thread is not blocked; it reacts whenever FTP is completed. – CompletableFuture<FTPStatus> ftp = CompletableFuture.supplyAsync(()->{ return FTPClient.uploadFile(file); }); ftp . whenComplete((ftpStatus,error)->{ //takes BiConsumer; alt. handle takes //BiFunction if (error == null){ //grab UI thread and update of successful FTP } else{ // grab UI thread and update of failure FTP } })
  19. 19. Creating APIs to return CompletableFuture • How to expose CompletableFuture APIs for Clients! • Instantiate CompletableFuture • Set result to it asynchronously. public CompletableFuture<String> getPageContent(URL url){ CompletableFuture<String> futurePage = CompletableFuture<>(); Runnable task = ()->{ try{ String htmlContent = fetchPageContent(url); //long running futurePage.complete(htmlContent); //not with classicFuture // this is why it is CompletableFut. }catch(Throwable th){ futurePage.completeExceptionally(th); //set complete exceptionally } }; exec.submit(task); return futurePage; }
  20. 20. Exception Handling • Exception Handling in CompletableFuture: – exceptionally() – handle() – whenComplete() • Time for Code  !
  21. 21. ReentrantReadWriteLock Precursor to StampedLock • java.util.concurrent.locks.ReentrantReadWriteLock – Pessimistic Write – Pessimistic Read – No Optimistic Locking
  22. 22. ReentrantReadWriteLock • ReentrantReadWriteLock Usage: private SomeClass theData; pri final ReadWriteLock myLocks = new ReentrantReadWriteLock(true); public void write(){ myLocks.writeLock().lock(); try{theData.write();} finally{myLocks.writeLock().unlock();} } public void read(){ myLocks.readLock().lock(); try{theData.read();} finally{myLocks.readLock().unlock();} }
  23. 23. StampedLock • JDK8 addition into package java.util.concurrent.locks – Works with versions of StampedLock – the “Stamp” – Modes • Pessimistic Write • Pessimistic Read • Optimistic Read! (Optimization)
  24. 24. Pessimistic StampedLocking Pessimistic Usage: private SomeClass theData; private final StampedLock lock= new StampedLock(true); public void write(){ long stamp = lock.writeLock(); try{theData.write();} finally{lock.writeLock(stamp);} } public void read(){ long stamp = lock.readLock(); try{theData.read();} finally{lock.unlockRead(stamp);} }
  25. 25. Optimistic StampedLock Optimistic usage: • try OptimisticRead • Validate optimisticRead stamp • Based on the validation take further action. • Lets Try!!! private int p1, p2 StampedLock lock = new StampedLock(); public void read(){ long stamp = lock.tryOptimisticRead(); int l1 = p1; int l2 = p2; if(lock.validate(stamp)){ //validate the stamp (version) process(l1, l2); }else{ stamp = lock.readLock()//acquire pessimistic locks try{l1 = p1; l2= p2; process(l1, l2); } finally{lock.unlockRead(stamp)} } }
  26. 26. Conclusion • CompletableFuture is powerful – Explore more – Write your own RxJava  • StampedLock is more efficient and optimized for particular use cases!

×