Slide 1

Slide 1 text

Loom is Blooming José Paumard Java Developer Advocate Java Platform Group Rémi Forax Maître de Conférences Université Gustave Eiffel

Slide 2

Slide 2 text

https://twitter.com/JosePaumard https://github.com/JosePaumard https://www.youtube.com/user/java https://www.youtube.com/user/JPaumard https://www.youtube.com/c/coursenlignejava https://www.youtube.com/hashtag/jepcafe https://fr.slideshare.net/jpaumard https://www.pluralsight.com/authors/jose-paumard

Slide 3

Slide 3 text

https://twitter.com/Nope! https://github.com/forax https://speakerdeck.com/forax OpenJDK, ASM, Tatoo, Pro, etc… One of the Father of invokedynamic (Java 7) Lambda (Java 8), Module (Java 9) Constant dynamic (Java 11) Record (Java 14 / 15) Valhalla (Java 19+)

Slide 4

Slide 4 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 4 https://dev.java/

Slide 5

Slide 5 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 5 https://dev.java/community/

Slide 6

Slide 6 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 6 https://inside.java/

Slide 7

Slide 7 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 7 https://jalba.scot 06/22 – 06/26

Slide 8

Slide 8 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 8 Don’t believe what we say! Loom is a Work in Progress

Slide 9

Slide 9 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 9 Don’t believe what we say! Loom is a Work in Progress

Slide 10

Slide 10 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 10 Don’t believe what we say! Loom is a Work in Progress http://jdk.java.net/loom/

Slide 11

Slide 11 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 11 It all Started with a Runnable…

Slide 12

Slide 12 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 12 1995: Thread, Runnable 1995: Threads and Runnables Runnable task = new Runnable() { void run() { System.out.println("I am running in thread " + Thread.currentThread().getName()); } }; Thread thread = new Thread(task); thread.start(); thread.join(); // blocks

Slide 13

Slide 13 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 13 1995: Thread, Runnable 1995: Threads and Runnables Object key = new Object(); synchronized(key) { System.out.println("Only one thread can execute me!"); }

Slide 14

Slide 14 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 14 2004: Java 5, java.util.concurrent 2004: Java Util Concurrent Callable task = new Callable() { @Override public String call() throws Exception { return "I am running in thread " + Thread.currentThread().getName(); } };

Slide 15

Slide 15 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 15 2004: Java 5, java.util.concurrent Wait lists inside! 2004: Java Util Concurrent ExecutorService service = Executors.newFixedThreadPool(4); Future future = service.submit(task);

Slide 16

Slide 16 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 16 2004: Java 5, java.util.concurrent 2004: Java Util Concurrent String result = future.get(); // blocks String result = future.get(10, TimeUnit.MICROSECONDS); boolean cancelled = future.cancel(true);

Slide 17

Slide 17 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 17 2004: Java 5, java.util.concurrent 2004: Java Util Concurrent Lock lock = new ReentrantLock(); lock.lock(); try { System.out.println("Only one thread can execute me!"); } finally { lock.unlock(); }

Slide 18

Slide 18 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 18 2004: Java 5, java.util.concurrent Plus many more concurrent classes: - Lock, Semaphore, Barrier, CountDownLatch - BlockingQueue, ConcurrentMap - CopyOnWriteArrayList 2004: Java Util Concurrent

Slide 19

Slide 19 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 19 2011 – 2014 (Java 7, Java 8): - Fork / Join, parallel Stream Allows to compute elements in parallel Two phases: - fork = splits a task in two sub-tasks - join = merge the result of two sub-tasks Uses work stealing to spread the tasks among threads 2011: Fork / Join

Slide 20

Slide 20 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 20 2011 – 2014 (Java 7, Java 8): - CompletionStage, CompletableFuture Subtype of Future Asynchronous programming model Allows to trigger tasks on the outcome of other tasks User can control which thread executes what task Exceptions handling 2014: CompletionStage

Slide 21

Slide 21 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 21 Once a thread begins to process a task it cannot release it Either the task completes with a result Or is completes with an exception It may be an InterruptedException One thing stays the same

Slide 22

Slide 22 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 22 2022+ (prev. in Java 19) 2023?: Loom!

Slide 23

Slide 23 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 23 Why Do We Need Concurrency?

Slide 24

Slide 24 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 24 Concurrency may be used in two different contexts: 1) Processing in-memory data in parallel, using all the CPU cores - Each thread uses 100% of your CPU cores - Threads are mostly not blocking Concurrency: Computations vs. I/O

Slide 25

Slide 25 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 25 Concurrency may be used in two different contexts: 2) Handling numerous blocking requests / responses HTTP Server  1 request <=|=> 1 thread DB Server  1 transaction <=|=> 1 thread Concurrency: Computations vs. I/O

Slide 26

Slide 26 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 26 Processing I/O data: - Each task waits for the data it needs to process Concurrency for I/O Preparing the request Time scale: 10ns

Slide 27

Slide 27 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 27 Processing I/O data: - Each task waits for the data it needs to process Concurrency for I/O Waiting for the response Time scale: 10ms

Slide 28

Slide 28 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 28 Processing I/O data: - Each task waits for the data it needs to process Concurrency for I/O Processing the response Time scale: 10ns

Slide 29

Slide 29 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 29 Processing I/O data: A Thread is idle 99.9999% of the time! How many threads do you need to keep your CPU busy? Concurrency for I/O ms ns ns

Slide 30

Slide 30 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 30 A thread is not cheap! - Thread startup time: ~1ms - Thread memory consumption: 2MB of stack - Context switching: ~100ms (depends on the OS) Having 1 million platform threads is not possible! Concurrency for I/O

Slide 31

Slide 31 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 31 How Many Threads Can I Run? ... 4065 4066 4067 4068 [0.373s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 2048k, guardsize: 16k, detached. [0.373s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread- 4066" Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached at java.base/java.lang.Thread.start0(Native Method) at java.base/java.lang.Thread.start(Thread.java:1451) at _3_how_many_platform_thread.printHowManyThreads(...java:19) at _3_how_many_platform_thread.main(...java:46) On a MacBook Air M1 (16GB of RAM)

Slide 32

Slide 32 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 32 CompletionState / CompletableFuture Asynchronous / Reactive programming Async / Await (C# or Kotlin) Mono / Multi (Spring) Uni / Multi (Quarkus) Solutions?

Slide 33

Slide 33 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 33 Breaking down a request handling into small stages Then compose them into a pipeline The code becomes: - hard to read and write (callback hell) - hard to debug (call stack?) - hard to test - hard to profile Solutions?

Slide 34

Slide 34 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 34 Loom to the Rescue

Slide 35

Slide 35 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 35 Virtual Thread! // platform threads var pthread = new Thread(() -> { System.out.println("platform " + Thread.currentThread()); }); pthread.start(); pthread.join();

Slide 36

Slide 36 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 36 Virtual Thread! // virtual threads var vthread = Thread.startVirtualThread(() -> { System.out.println("virtual " + Thread.currentThread()); }); vthread.join(); // platform threads var pthread = Thread.ofPlatform(() -> { System.out.println("platform " + Thread.currentThread()); }); pthread.join();

Slide 37

Slide 37 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 37 A virtual thread runs on a carrier thread from a Fork-Join pool (not the common fork join pool) This pool implements a FIFO queue (instead of a LIFO one) Virtual Thread! // platform threads platform Thread[#14,Thread-0,5,main] // virtual threads virtual VirtualThread[#15]/runnable@ForkJoinPool-1-worker-1

Slide 38

Slide 38 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 38 Thread Polymorphic Builder // platform threads var pthread = Thread.ofPlatform() .name("platform-", 0) .start(() -> { System.out.println("platform " + Thread.currentThread()); }); pthread.join(); // virtual threads var vthread = Thread.ofVirtual() .name("virtual-", 0) .start(() -> { System.out.println("virtual " + Thread.currentThread()); }); vthread.join();

Slide 39

Slide 39 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 39 How many virtual threads can I run?

Slide 40

Slide 40 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 40 Platform/OS thread (starts in ms) - Creates a 2MB stack upfront - System call to ask the OS to schedule the thread Virtual thread (starts in μs) - Grow and shrink the stack dynamically - Use a specific fork-join pool of platform threads (carrier threads) - One platform thread per core Running a Thread

Slide 41

Slide 41 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 41 How does it work under the hood?

Slide 42

Slide 42 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 42 Continuation

Slide 43

Slide 43 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 43 Example of Thread.sleep(): Calls Contination.yield() Where Does the Magic Come From? @ChangesCurrentThread private boolean yieldContinuation() { boolean notifyJvmti = notifyJvmtiEvents; // unmount if (notifyJvmti) notifyJvmtiUnmountBegin(false); unmount(); try { return Continuation.yield(VTHREAD_SCOPE); } finally { // re-mount mount(); if (notifyJvmti) notifyJvmtiMountEnd(false); } }

Slide 44

Slide 44 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 44 yield() copies the stack to the heap Continuation.yield() heap stack start() Platform thread 1 sleep()

Slide 45

Slide 45 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 45 run() copies from the heap to another stack (optimization: only copies the topmost stack frames) Continuation.run() stack start() Platform thread 1 heap

Slide 46

Slide 46 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 46 run() copies from the heap to another stack (optimization: only copies the topmost stack frames) Continuation.run() stack start() Platform thread 1 stack Platform thread 2 heap

Slide 47

Slide 47 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 47 jdk.internal.vm.Continuation var scope = new ContinuationScope("hello"); var continuation = new Continuation(scope, () -> { System.out.println("C1"); Continuation.yield(scope); System.out.println("C2"); Continuation.yield(scope); System.out.println("C3"); }); System.out.println("start"); continuation.run(); System.out.println("came back"); continuation.run(); System.out.println("back again"); continuation.run(); System.out.println("back again again"); Execution: start C1 came back C2 back again C3 back again again

Slide 48

Slide 48 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 48 A Platform Thread is a thin wrapper on an OS Thread A Virtual Thread is not tied to a particular OS Thread A Virtual Thread only consumes an OS Thread when it performs calculations on the CPU Running a Virtual Thread

Slide 49

Slide 49 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 49 Creating a virtual thread is cheap Blocking a virtual thread is cheap Pooling virtual threads is useless

Slide 50

Slide 50 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 50 Two strategies for concurrency - Competitive: all threads compete for the CPUs/cores - Cooperative: each thread hand of the CPUs to the next Loom implementation does both - OS schedule carrier threads to CPU/cores and - JDK codes schedule virtual threads to carrier threads Loom Internals

Slide 51

Slide 51 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 51 Most of the code of the virtual threads scheduling is written in Java in the JDK (jdk.internal.vm.Continuation) Written in C in the JVM: - Copy of the stack frames back and forth - GCs modified to find references in stack on heap Loom is not Implemented « By the JVM »

Slide 52

Slide 52 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 52 All blocking codes are changed to - Check if current thread is a virtual thread - If it is, instead of blocking: - Register a handler that will be called when the OS is ready (using NIO) - Call Continuation.yield() - When the handler is called, find a carrier thread and call Continuation.start() In the JDK

Slide 53

Slide 53 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 53 Sometimes virtual threads are pinned to their carrier thread Synchronized block are written in assembly and uses an address on the stack the stack frames can not be copied Prefer ReentrantLock over synchronized() There Are Cases Where It Does Not Work

Slide 54

Slide 54 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 54 Sometimes virtual threads are pinned to their carrier thread Native code that does an upcall to Java may use an address on stack the stack frames can not be copied There Are Cases Where It Does Not Work

Slide 55

Slide 55 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 55 Java 13 - JEP 353 Reimplement the Legacy Socket API Java 14 - JEP 373 Reimplement the Legacy Datagram Socket API - JEP 374 Deprecate and Disable Biased Locking Stealth Rewrite of the JDK for Loom

Slide 56

Slide 56 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 56 Java 18 - JEP 416 Reimplement Core Reflection with Method Handles - JEP 418 (Internet-Address Resolution SPI) in JDK 18 defined a service-provider interface for host name and address lookup. This will allow third-party libraries to implement alternative java.net.InetAddress resolvers that do not pin threads during host lookup Stealth Rewrite of the JDK for Loom

Slide 57

Slide 57 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 57 The JDK creates as many virtual threads as the user want - Mount a virtual thread to an available carrier thread when starting - If blocking, unmount the current virtual thread and mount another virtual thread Loom Idea: Under the Hood

Slide 58

Slide 58 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 58 ThreadLocal are evil! But still working ThreadLocal variables are stored in a HashMap. What about having 1 million HashMap? How can a ThreadLocal variable exist when a task can switch from one thread (virtual / platform) to the other? What About ThreadLocal?

Slide 59

Slide 59 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 59 (It was called ScopeLocal in a previous version) Runs across thread (platform / virtual) ExtentLocal to the Rescue! ExtentLocal KEY = ExtentLocal.newInstance(); Runnable task = () -> System.out.printn("Key is " + KEY.get()); Runnable taskA = () -> ExtentLocal.where(KEY, "Value A").run(taskA);

Slide 60

Slide 60 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 60 Structured Concurrency

Slide 61

Slide 61 text

Coffee (or whatever) Break!

Slide 62

Slide 62 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 62 Structured Concurrency

Slide 63

Slide 63 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 63 A travel agency sells travels. On the response page, it wants to display: - the quotation - the weather forecast for the destination The Travel Agency Example

Slide 64

Slide 64 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 64 The Travel Agency Example Quotation Weather Forecast Travel Page

Slide 65

Slide 65 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 65 1) If getQuotation() fails, getTravelPage() fails and getWeather() is not called Synchronous Travel Agency Page getTravelPage() { Quotation quotation = getQuotation(); // exception? Weather weather = getWeather(); // exception? return buildPage(quotation, weather); }

Slide 66

Slide 66 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 66 2) If the getTravelPage() thread is interrupted, everything is interrupted. Synchronous Travel Agency Page getTravelPage() { Quotation quotation = getQuotation(); // exception? Weather weather = getWeather(); // exception? return buildPage(quotation, weather); }

Slide 67

Slide 67 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 67 3) A stack trace shows you that you are running getQuotation(), called by getTravelPage(). Synchronous Travel Agency Page getTravelPage() { Quotation quotation = getQuotation(); // exception? Weather weather = getWeather(); // exception? return buildPage(quotation, weather); } org.paumard.loom.LoomExample.getQuotation(LoomExample.java:99) org.paumard.loom.LoomExample.getTravelPage(LoomExample.java:20) org.paumard.loom.LoomExample.main(LoomExample.java:16)

Slide 68

Slide 68 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 68 Problems: - Latency grows with the number of requests - Your CPU is used at 0.00001% Synchronous Travel Agency

Slide 69

Slide 69 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 69 ExecutorService Based Travel Agency ExecutorService service = ...; Page getTravelPage() { Future quotation = service.submit(() -> getQuotation()); Future weather = service.submit(() -> getWeather()); return buildPage(quotation.get(), weather.get()); }

Slide 70

Slide 70 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 70 1) If getQuotation() fails, getTravelPage() fails, but getWeather() is still running ExecutorService Based Travel Agency Future quotation = service.submit(() -> getQuotation()); Future weather = service.submit(() -> getWeather());

Slide 71

Slide 71 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 71 2) If getTravelPage() is interrupted, then getQuotation() and getWeather() don’t know it. ExecutorService Based Travel Agency Page getTravelPage() { Future quotation = service.submit(() -> getQuotation()); Future weather = service.submit(() -> getWeather()); return buildPage(quotation.get(), weather.get()); }

Slide 72

Slide 72 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 72 3) What about the stack trace? ExecutorService Based Travel Agency Page getTravelPage() { Future quotation = service.submit(() -> getQuotation()); Future weather = service.submit(() -> getWeather()); return buildPage(quotation.get(), weather.get()); }

Slide 73

Slide 73 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 73 Stack trace org.paumard.loom.LoomExample.getQuotation(LoomExample.java:107) org.paumard.loom.LoomExample.lambda$getTravelPage$0(LoomExample.java:28) java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1143) org.paumard.loom.LoomExample.getQuotation(LoomExample.java:110) org.paumard.loom.LoomExample.lambda$static$0(LoomExample.java:25) java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1143) org.paumard.loom.LoomJunk.getQuotation(LoomJunk.java:110) java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1143)

Slide 74

Slide 74 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 74 CompletableFuture Based Travel Agency var quotationCF = CompletableFuture.supplyAsync(() -> getQuotation()); var weatherCF = CompletableFuture.supplyAsync(() -> getWeather()); CompletableFuture travelPageCF = quotationCF.thenCompose( quotation -> weatherCF .thenApply( weather -> buildPage(quotation, weather)));

Slide 75

Slide 75 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 75 1) If getQuotation() fails, getTravelPage() fails, and getWeather() is still called CompletableFuture Based Travel Agency var quotationCF = CompletableFuture.supplyAsync(() -> getQuotation()); var weatherCF = CompletableFuture.supplyAsync(() -> getWeather());

Slide 76

Slide 76 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 76 1) If getQuotation() fails, getTravelPage() fails, you can cancel getWeather() CompletableFuture Based Travel Agency CompletableFuture travelPageCF = quotationCF .exceptionally(t -> { weatherCF.cancel(true); throw new RuntimeException(t); }) .thenCompose(...);

Slide 77

Slide 77 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 77 2) If getWeather() fails, you can handle the exception nicely CompletableFuture Based Travel Agency CompletableFuture travelPageCF = quotationCF.thenCompose( quotation -> weatherCF // .completeOnTimeout(Weather.UNKNOWN, 100, MILLISECONDS) .exceptionally(e -> Weather.UNKNOWN) .thenApply( weather -> buildPage(quotation, weather)));

Slide 78

Slide 78 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 78 CompletableFuture Based Travel Agency var quotationCF = CompletableFuture.supplyAsync(() -> getQuotation()); var weatherCF = CompletableFuture.supplyAsync(() -> getWeather()); CompletableFuture travelPageCF = quotationCF .exceptionally(t -> { weatherCF.cancel(true); throw new RuntimeException(t); }) .thenCompose( quotation -> weatherCF // .completeOnTimeout(Weather.UNKNOWN, 100, MILLISECONDS) .exceptionally(e -> Weather.UNKNOWN) .thenApply( weather -> buildPage(quotation, weather)));

Slide 79

Slide 79 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 79 3) If getTravelPage() is interrupted, you cannot interrupt getQuotation() nor getWeather() 4) And what about the stack trace? CompletableFuture Based Travel Agency

Slide 80

Slide 80 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 80 CompletableFuture Based Travel Agency org.paumard.loom.LoomExample.getQuotation(LoomExample.java:125) org.paumard.loom.LoomExample.lambda$getTravelPage$2(LoomExample.java:38) java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) org.paumard.loom.LoomExample.getWeather(LoomExample.java:123) org.paumard.loom.LoomExample.lambda$getTravelPage$3(LoomExample.java:40) java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)

Slide 81

Slide 81 text

Quotation Server A 5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 81 The Travel Agency Example Quotation Server B Quotation Server C Weather Forecast Server A Weather Forecast Server B Weather Forecast Server C Travel Agency

Slide 82

Slide 82 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 82 It needs to be closed (try with resources FTW!) It creates virtual threads on demand Pattern: - Launch tasks - Call join() - Get the results Structured Scope

Slide 83

Slide 83 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 83 A StructuredTaskScope object looks like an ExecutorService - It takes tasks and run then - And returns Future But: - An executor lives with your application - A task scope lives with your tasks StructuredTaskScope

Slide 84

Slide 84 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 84 - ShutdownOnSuccess - ShutdownOnFailure Can be extended to implement specific needs StructuredTaskScope

Slide 85

Slide 85 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 85 Allows you to implement your own logic and error handling handleComplete(Future<>) is the method you need to override Extending StructuredTaskScope

Slide 86

Slide 86 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 86 Stack Trace, ThreadDumps? > jcmd Thread.dump_to_file –format-json

Slide 87

Slide 87 text

5/14/2022 Copyright © 2021, Oracle and/or its affiliates | 87 Allows you to bind elements to a scope Your tasks can read these elements, and use them Use ExtentLocal sparsely and wisely! ExtentLocal

Slide 88

Slide 88 text

Loom is Great!