|
| 1 | +import java.util.concurrent.StructuredTaskScope; |
| 2 | + |
| 3 | +public class Test1 { |
| 4 | + public static void main(String[] args) { |
| 5 | + |
| 6 | + try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { |
| 7 | + |
| 8 | + var task1 = scope.fork(() -> fetchData("User Data")); |
| 9 | + var task2 = scope.fork(() -> fetchData("Order Data")); |
| 10 | + |
| 11 | + scope.join(); // Wait for all tasks |
| 12 | + scope.throwIfFailed(); // Throw if any failed |
| 13 | + |
| 14 | + System.out.println(task1.get()); |
| 15 | + System.out.println(task2.get()); |
| 16 | + |
| 17 | + } catch (Exception e) { |
| 18 | + e.printStackTrace(); |
| 19 | + } |
| 20 | + } |
| 21 | + |
| 22 | + static String fetchData(String name) throws InterruptedException { |
| 23 | + Thread.sleep(1000); // simulate delay |
| 24 | + return "Fetched: " + name; |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +/* |
| 29 | +What changed: Previous vs New |
| 30 | +
|
| 31 | +Previous Java style: |
| 32 | +- Usually we used ExecutorService + Future |
| 33 | +- We manually submitted tasks |
| 34 | +- We manually waited for results |
| 35 | +- We manually handled cancellation/shutdown |
| 36 | +- Error handling was more scattered |
| 37 | +- Related tasks were not clearly grouped as one unit of work |
| 38 | +
|
| 39 | +New Java 26 style: |
| 40 | +- Uses StructuredTaskScope for structured concurrency |
| 41 | +- Related concurrent tasks are written inside one clear block |
| 42 | +- Task lifetime is bound to the scope block |
| 43 | +- ShutdownOnFailure stops the whole operation if one subtask fails |
| 44 | +- join() waits for all relevant subtasks |
| 45 | +- throwIfFailed() propagates failure clearly |
| 46 | +
|
| 47 | +Old approach example idea: |
| 48 | +ExecutorService executor = Executors.newFixedThreadPool(2); |
| 49 | +Future<String> f1 = executor.submit(() -> fetchData("User Data")); |
| 50 | +Future<String> f2 = executor.submit(() -> fetchData("Order Data")); |
| 51 | +
|
| 52 | +System.out.println(f1.get()); |
| 53 | +System.out.println(f2.get()); |
| 54 | +executor.shutdown(); |
| 55 | +
|
| 56 | +Why the new approach is better: |
| 57 | +- Cleaner and easier to read |
| 58 | +- Better structured code |
| 59 | +- Safer cancellation model |
| 60 | +- Better error propagation |
| 61 | +- Related tasks are managed together |
| 62 | +- Reduces thread leaks and forgotten shutdown problems |
| 63 | +
|
| 64 | +Pros: |
| 65 | +1. Better readability |
| 66 | + - Parent task and child tasks are grouped together |
| 67 | +
|
| 68 | +2. Better reliability |
| 69 | + - If one task fails, ShutdownOnFailure can cancel the others |
| 70 | +
|
| 71 | +3. Easier maintenance |
| 72 | + - Concurrency logic is easier to understand later |
| 73 | +
|
| 74 | +4. Better observability |
| 75 | + - Structured concurrency treats subtasks as part of one operation |
| 76 | +
|
| 77 | +5. Automatic resource management |
| 78 | + - try-with-resources closes the scope properly |
| 79 | +
|
| 80 | +Cons: |
| 81 | +1. Preview feature |
| 82 | + - StructuredTaskScope is still a preview API in Java 26 |
| 83 | +
|
| 84 | +2. Must enable preview |
| 85 | + - Compile and run with --enable-preview |
| 86 | +
|
| 87 | +3. Not ideal for every use case |
| 88 | + - For long-running independent background jobs, ExecutorService may still fit better |
| 89 | +
|
| 90 | +4. Learning curve |
| 91 | + - Developers familiar with old concurrency APIs need time to adapt |
| 92 | +
|
| 93 | +Best use case: |
| 94 | +- When one request/task is split into multiple related subtasks |
| 95 | +- Example: fetch user data + fetch order data + fetch payment data together |
| 96 | +
|
| 97 | +Compile and run: |
| 98 | +javac --enable-preview --release 26 Test1.java |
| 99 | +java --enable-preview Test1 |
| 100 | +*/ |
0 commit comments