GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • java.evolved
  • ←
  • →

This view

  • Original page
  • New address

GeezerVison is showing javaevolved.dev — Structured concurrency | java.evolved

Home / Concurrency / Structured concurrency
Concurrency Advanced

Structured concurrency

  • 🐛 Report a code issue
  • 🌐 Report a translation issue
  • 💡 Suggest a new pattern

Manage concurrent task lifetimes as a single unit of work.

Concurrency Virtual Threads
Code Comparison
✕ Java 8
ExecutorService exec =
    Executors.newFixedThreadPool(2);
Future<User> u = exec.submit(this::fetchUser);
Future<Order> o = exec.submit(this::fetchOrder);
try {
    return combine(u.get(), o.get());
} finally { exec.shutdown(); }
✓ Java 25 (Preview)
try (var scope = new StructuredTaskScope
        .ShutdownOnFailure()) {
    var u = scope.fork(this::fetchUser);
    var o = scope.fork(this::fetchOrder);
    scope.join().throwIfFailed();
    return combine(u.get(), o.get());
}
Share 𝕏
See a problem with this code? Let us know.
Why the modern way wins
🛡️

No thread leaks

All forked tasks complete before the scope closes.

⚡

Fast failure

ShutdownOnFailure cancels siblings if one fails.

📐

Clear structure

Task lifetime matches the lexical scope in code.

Old Approach
Manual Thread Lifecycle
Modern Approach
StructuredTaskScope
Since JDK
25
Difficulty
Advanced
JDK Support
Structured concurrency
Preview

Preview in JDK 25 (fifth preview, JEP 505). Requires --enable-preview.

How it works

Structured concurrency treats a group of concurrent tasks as one operation. If any subtask fails, the others are cancelled. The scope ensures no thread leaks and gives clear parent-child relationships.

Related Documentation
Structured Concurrency (JEP 499) ↗ StructuredTaskScope ↗
Proof
View proof source ↗
Related patterns
Concurrency Beginner

Virtual threads

Java 8
Thread thread = new Thread(() -> {
    System.out.println("hello");
});
thread.start();
thread.join();
Java 21+
Thread.startVirtualThread(() -> {
    IO.println("hello");
}).join();
Hover to see modern ➜
JDK 21+ →
Concurrency Advanced

Scoped values

Java 8
static final ThreadLocal<User> CURRENT =
    new ThreadLocal<>();
void handle(Request req) {
    CURRENT.set(authenticate(req));
    try { process(); }
    finally { CURRENT.remove(); }
}
Java 25
static final ScopedValue<User> CURRENT =
    ScopedValue.newInstance();
void handle(Request req) {
    ScopedValue.where(CURRENT,
        authenticate(req)
    ).run(this::process);
}
Hover to see modern ➜
JDK 25+ →
Concurrency Advanced

Stable values

Java 8
private volatile Logger logger;
Logger getLogger() {
    if (logger == null) {
        synchronized (this) {
            if (logger == null)
                logger = createLogger();
        }
    }
    return logger;
}
Java 25 (Preview)
private final StableValue<Logger> logger =
    StableValue.of(this::createLogger);

Logger getLogger() {
    return logger.get();
}
Hover to see modern ➜
JDK 25+ →
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.