Add structured-concurrency-final module: StructuredTaskScope final in JDK 28 (JEP 543), run on 28-ea, 27, 26 and 25
Runnable demos for the ankurm.com structured-concurrency-java article: the ExecutorService thread leak and its fix, every built-in Joiner, structure violations, timeouts, a custom Joiner, JSON thread dumps (in-process and jcmd), scoped values, javap diffs of the API on 25, 26, 27 and 28-ea, compiler output for six pieces of 25/26-era code, and the preview class-file trap between 27 and 28. Transcripts in output/. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01CifR2BE7PBvRy5hT8TS9oz
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
import java.util.concurrent.StructuredTaskScope.Joiner;
|
||||
|
||||
/** Joiner.awaitAll() existed in 25 and 26 and was removed in 27. */
|
||||
public class AwaitAll {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (var scope = StructuredTaskScope.open(Joiner.<String>awaitAll())) {
|
||||
scope.fork(() -> "x");
|
||||
scope.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
|
||||
/** Valid on JDK 25 and 26 (join() threw only InterruptedException). On 27 and 28 join() can throw ExecutionException. */
|
||||
public class MissingCatch {
|
||||
static String handle() throws InterruptedException {
|
||||
try (var scope = StructuredTaskScope.open()) {
|
||||
var user = scope.fork(() -> "Alice");
|
||||
scope.join();
|
||||
return user.get();
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) throws Exception { System.out.println(handle()); }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
|
||||
/** The JDK 25/26 way to catch a failed scope. FailedException is gone in 27. */
|
||||
public class OldFailedException {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (var scope = StructuredTaskScope.open()) {
|
||||
scope.fork(() -> { throw new IllegalStateException("boom"); });
|
||||
scope.join();
|
||||
} catch (StructuredTaskScope.FailedException e) {
|
||||
System.out.println("cause: " + e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.StructuredTaskScope.Joiner;
|
||||
import java.util.concurrent.StructuredTaskScope.Subtask;
|
||||
|
||||
/** A custom Joiner as written for JDK 26: two type parameters and onTimeout(). */
|
||||
public class OldJoiner<T> implements Joiner<T, List<T>> {
|
||||
private final java.util.Queue<T> results = new ConcurrentLinkedQueue<>();
|
||||
public boolean onComplete(Subtask<T> s) { if (s.state() == Subtask.State.SUCCESS) results.add(s.get()); return false; }
|
||||
public void onTimeout() { }
|
||||
public List<T> result() { return List.copyOf(results); }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
|
||||
/** The JDK 25/26 timeout exception. In 27 the scope throws ExecutionException with a CancelledByTimeoutException cause. */
|
||||
public class OldTimeoutException {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (var scope = StructuredTaskScope.open(StructuredTaskScope.Joiner.<String>awaitAllSuccessfulOrThrow(),
|
||||
cf -> cf.withTimeout(Duration.ofMillis(50)))) {
|
||||
scope.fork(() -> { Thread.sleep(1000); return "late"; });
|
||||
scope.join();
|
||||
} catch (StructuredTaskScope.TimeoutException e) {
|
||||
System.out.println("timed out");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import java.util.concurrent.StructuredTaskScope;
|
||||
|
||||
/** The JDK 21-24 API that older tutorials still show. It is not in 25 or later. */
|
||||
public class ShutdownOnFailure {
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
|
||||
var user = scope.fork(() -> "Alice");
|
||||
scope.join().throwIfFailed();
|
||||
System.out.println(user.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user