Warning: Undefined array key "HTTP_ACCEPT_LANGUAGE" in /home/bibiizjb/ptutorials.com/en/account/functions/check_point_2.php on line 25
Java Multithreading & Concurrency (ExecutorService, ForkJoinPool) Tutorial

Java Multithreading & Concurrency: ExecutorService and ForkJoinPool Tutorial

Java provides powerful tools for managing multithreading and concurrency, such as the ExecutorService and ForkJoinPool. These tools simplify the process of creating and managing threads, allowing you to focus on writing concurrent and parallel tasks. This tutorial will guide you through the basics of using ExecutorService and ForkJoinPool to build efficient and scalable multithreaded applications.

By the end of this tutorial, you'll understand how to use ExecutorService for thread pooling and ForkJoinPool for parallel task execution in Java.

ExecutorService

The ExecutorService is a higher-level replacement for working with threads directly. It manages a pool of threads and allows you to submit tasks for execution.

  • Key Features:
    • Manages a pool of threads to execute tasks.
    • Supports task submission, execution, and shutdown.
    • Provides methods for tracking task completion (e.g., Future).
  • Creating an ExecutorService:
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executor = Executors.newFixedThreadPool(4); // Create a thread pool with 4 threads
    
            for (int i = 0; i < 10; i++) {
                executor.submit(() -> {
                    System.out.println("Task executed by " + Thread.currentThread().getName());
                });
            }
    
            executor.shutdown(); // Shutdown the executor
        }
    }
  • Using Future:
    import java.util.concurrent.*;
    
    public class Main {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            Future<Integer> future = executor.submit(() -> {
                Thread.sleep(1000);
                return 42;
            });
    
            System.out.println("Result: " + future.get()); // Blocks until the result is available
            executor.shutdown();
        }
    }

ForkJoinPool

The ForkJoinPool is a special thread pool designed for parallel execution of tasks that can be broken down into smaller subtasks. It is particularly useful for divide-and-conquer algorithms.

  • Key Features:
    • Optimized for recursive task splitting and parallel execution.
    • Uses work-stealing to balance the load across threads.
    • Supports tasks of type ForkJoinTask (e.g., RecursiveTask, RecursiveAction).
  • Example: RecursiveTask:
    import java.util.concurrent.*;
    
    class SumTask extends RecursiveTask {
        private final long[] numbers;
        private final int start;
        private final int end;
    
        SumTask(long[] numbers, int start, int end) {
            this.numbers = numbers;
            this.start = start;
            this.end = end;
        }
    
        @Override
        protected Long compute() {
            if (end - start <= 1000) { // Base case
                long sum = 0;
                for (int i = start; i < end; i++) {
                    sum += numbers[i];
                }
                return sum;
            } else { // Split task
                int mid = (start + end) / 2;
                SumTask leftTask = new SumTask(numbers, start, mid);
                SumTask rightTask = new SumTask(numbers, mid, end);
                leftTask.fork(); // Asynchronously execute the left task
                return rightTask.compute() + leftTask.join(); // Wait for the left task and combine results
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            long[] numbers = new long[10_000];
            for (int i = 0; i < numbers.length; i++) {
                numbers[i] = i + 1;
            }
    
            ForkJoinPool pool = new ForkJoinPool();
            long result = pool.invoke(new SumTask(numbers, 0, numbers.length));
            System.out.println("Sum: " + result); // Output: Sum: 50005000
        }
    }

Choosing Between ExecutorService and ForkJoinPool

Selecting the right tool depends on your specific use case:

  • Use ExecutorService:
    • For general-purpose thread pooling.
    • When tasks are independent and do not need to be split into subtasks.
  • Use ForkJoinPool:
    • For divide-and-conquer algorithms.
    • When tasks can be recursively split into smaller subtasks.

This tutorial covered the basics of multithreading and concurrency in Java using ExecutorService and ForkJoinPool. Practice using these tools to build efficient and scalable concurrent applications.

0 Interaction 0 Views 0 likes
Heart Button
×
×
🍪 CookieConsent@Ptutorials:~

Welcome to Ptutorials

Note: We aim to make learning easier by sharing top-quality tutorials, but please remember that tutorials may not be 100% accurate, as occasional mistakes can happen. Once you've mastered the language, we highly recommend consulting the official documentation to stay updated with the latest changes. If you spot any errors, please feel free to report them to help us improve.

We kindly ask that you refrain from posting interactions unrelated to web development, such as political, sports, or other non-web-related content. Please be respectful and interact with other members in a friendly manner. By participating in discussions and providing valuable answers, you can earn points and level up your profile.

$ Allow cookies on this site ? (y/n)

top-home