Structured Concurrency in Java
Last Updated :
14 May, 2023
Structured concurrency organizes concurrent processes in a controlled way to ease concurrent execution. It prevents race situations, deadlocks, and orphaned jobs. Structured concurrency may be implemented in Java utilizing libraries, frameworks, or experimental initiatives like Project Loom. Structured concurrency concepts and techniques in Java:
- ExecutorService and CompletableFuture
- ForkJoinPool and RecursiveTask
ExecutorService and CompletableFuture
ExecutorService in java.util.concurrent manages a pool of worker threads that may perform tasks simultaneously. CompletableFuture lets you link, manage, and combine tasks. ExecutorService and CompletableFuture provide systematic concurrency management of concurrent processes.
Example:
Java
import java.util.concurrent.*;
public class StructuredConcurrencyExample {
public static void main(String[] args)
throws InterruptedException, ExecutionException
{
ExecutorService executor
= Executors.newFixedThreadPool( 3 );
CompletableFuture<Void> task1
= CompletableFuture.runAsync(() -> {
System.out.println( "Task 1 started" );
}, executor);
CompletableFuture<Void> task2
= CompletableFuture.runAsync(() -> {
System.out.println( "Task 2 started" );
}, executor);
CompletableFuture<Void> combinedTasks
= CompletableFuture.allOf(task1, task2);
combinedTasks.get();
executor.shutdown();
}
}
|
Output
Task 1 started
Task 2 started
Note: The order of the task outputs may vary because the tasks are executed concurrently, and the order in which they complete may not be the same each time.
ForkJoinPool and RecursiveTask
ForkJoinPool, another concurrency framework in the java.util.concurrent package efficiently executes divide-and-conquer algorithms and steals work. ForkJoinPool with RecursiveTask or RecursiveAction creates organized concurrent tasks.
Example:
Java
import java.util.concurrent.*;
public class StructuredConcurrencyExample {
public static void main(String[] args)
{
ForkJoinPool forkJoinPool = new ForkJoinPool();
RecursiveAction task1 = new RecursiveAction() {
@Override protected void compute()
{
System.out.println( "Task 1 started" );
}
};
RecursiveAction task2 = new RecursiveAction() {
@Override protected void compute()
{
System.out.println( "Task 2 started" );
}
};
ForkJoinTask<Void> submittedTask1
= forkJoinPool.submit(task1);
ForkJoinTask<Void> submittedTask2
= forkJoinPool.submit(task2);
submittedTask1.join();
submittedTask2.join();
forkJoinPool.shutdown();
}
}
|
Output
Task 1 started
Task 2 started
Note: The order of the task outputs may vary because the tasks are executed concurrently, and the order in which they complete may not be the same each time.
Share your thoughts in the comments
Please Login to comment...