Advanced concurrency

advconcurrency7StructuredConcurrency

Path
pkg16advconcurrency/advconcurrency7StructuredConcurrency.java
Package
pkg16advconcurrency
Study order
7
Run
Single-file source launch
Command
java pkg16advconcurrency/advconcurrency7StructuredConcurrency.java
Example
Stable demo; Java 25 preview API is only in the comment
Requires
Java 8

There is no in-browser runner. This is the file from the curriculum, unchanged.

pkg16advconcurrency/advconcurrency7StructuredConcurrency.java
1package pkg16advconcurrency;2 3import java.util.concurrent.CompletableFuture;4import java.util.concurrent.TimeUnit;5 6/*7 * advconcurrency7StructuredConcurrency.java8 * -----------------------------------------9 * The main method uses CompletableFuture. That code needs Java 8 and does not10 * use --enable-preview.11 *12 * Structured concurrency is still a preview in Java 25 (JEP 505). It is not13 * final. A program that calls it must be compiled and run with --enable-preview.14 * Java 25 opens a scope with StructuredTaskScope.open and a Joiner. It does not15 * use a public constructor:16 *17 *   try (var scope = StructuredTaskScope.open(18 *           StructuredTaskScope.Joiner.<String>anySuccessfulResultOrThrow())) {19 *       scope.fork(() -> fetchFrom("primary", 200));20 *       scope.fork(() -> fetchFrom("backup", 50));21 *       return scope.join();22 *   }23 *24 * Earlier previews used a public constructor. That shape is not the Java 25 API.25 */26public class advconcurrency7StructuredConcurrency {27 28    static String fetchFrom(String source, int delayMs) throws InterruptedException {29        Thread.sleep(delayMs);30        return "data-from-" + source;31    }32 33    public static void main(String[] args) throws Exception {34        // Failover race: first successful result wins (CompletableFuture stable equivalent)35        CompletableFuture<String> primary = CompletableFuture.supplyAsync(() -> {36            try { return fetchFrom("primary", 200); } catch (InterruptedException e) {37                Thread.currentThread().interrupt(); throw new RuntimeException(e);38            }39        });40        CompletableFuture<String> backup = CompletableFuture.supplyAsync(() -> {41            try { return fetchFrom("backup", 50); } catch (InterruptedException e) {42                Thread.currentThread().interrupt(); throw new RuntimeException(e);43            }44        });45 46        String winner = primary.applyToEither(backup, s -> s)47                .get(1, TimeUnit.SECONDS);48        System.out.println("Race winner: " + winner);49 50        // All must succeed in parallel51        CompletableFuture<String> db = CompletableFuture.supplyAsync(() -> {52            try { return fetchFrom("db", 30); } catch (InterruptedException e) {53                Thread.currentThread().interrupt(); throw new RuntimeException(e);54            }55        });56        CompletableFuture<String> cache = CompletableFuture.supplyAsync(() -> {57            try { return fetchFrom("cache", 20); } catch (InterruptedException e) {58                Thread.currentThread().interrupt(); throw new RuntimeException(e);59            }60        });61        System.out.println("Parallel: " + db.get() + " + " + cache.get());62    }63}