Simple Implementation of Thread Pool: A Must-Read Guide for Java Thread Pool Beginners

"As a Java developer, have you ever encountered the problem of too many threads concurrency? When there are too many threads, it will lead to waste of resources, degraded application performance, and even thread deadlock. So, is there an effective way Manage threads efficiently and avoid these problems? The answer is yes, that is the thread pool. In this article, we will explore the mysteries of the thread pool from the perspective of Java, gain an in-depth understanding of the advantages of the thread pool, and learn how to use the thread pool to achieve multiple Thread concurrency."

How is the thread pool created?

There are mainly two types of methods for creating thread pools in JAVA. One is the method provided by the Executors factory class, which provides 4 different thread pools for use. The other is custom creation through the ThreadPoolExecutor class.

Executors factory class

// Five thread pools:
//     ExecutorService threadPool = null;
//     threadPool = Executors.newCachedThreadPool();//A buffered thread pool, the number of threads is controlled by the JVM
//     threadPool = Executors.newFixedThreadPool(3);//fixed size thread pool
//     threadPool = Executors.newScheduledThreadPool(2); // Has delay and timing functions
//     threadPool = Executors.newSingleThreadExecutor();//Single-threaded thread pool, only one thread is working
//     threadPool = new ThreadPoolExecutor();//The default thread pool has many controllable parameters   

private static void createCachedThreadPool() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(() -> {
                // Get thread name, default format: pool-1-thread-1
                System.out.println(DateUtil.now() + " " + Thread.currentThread().getName() + " " + index);
                // wait 2 seconds
                sleep(2000);
            });
        }
    }

ThreadPoolExecutor class

ThreadPoolExecutor provides a construction method, you need to set specific parameters yourself, which is more flexible

public ThreadPoolExecutor(int corePoolSize, // number of core threads
                              int maximumPoolSize, // max worker threads
                              long keepAliveTime, // Survival time, how long the thread will last when there is no task to execute before it will be terminated.
                              TimeUnit unit, // time unit
                              BlockingQueue<Runnable> workQueue, // work queue
                              ThreadFactory threadFactory, // The thread factory is mainly used to create threads, defaulting to normal priority, non-daemon threads.
                              RejectedExecutionHandler handler // Rejection strategy, when a new thread is created so that the number of threads is greater than the maximum thread, it will be executed
                              ) {
        // omit...
    }

The main parameters of the thread pool

  • corePoolSize number of core threads
    The number of core threads, the number of threads that are always alive in the thread pool.
  • BlockingQueue work queue
    workQueue = new ArrayBlockingQueue<>(5);//Array-based first-in-first-out queue, bounded
    workQueue = new LinkedBlockingQueue<>();//First-in-first-out queue based on linked list, unbounded
    workQueue = new SynchronousQueue<>();//unbuffered waiting queue, unbounded
  • threadFactory thread factory
    It is used to set the factory for creating threads, which can be created for each thread factory. Thread settings with more meaningful names. Use the ThreadFactoryBuilder provided by the open source framework guava to quickly set meaningful names for the threads in the thread pool. The code is as follows:

    new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build();
  • handler
    Reject policy, the policy when rejecting the task, 4 options, the default is AbortPolicy.
parameterdescribe
AbortPolicyreject and throw an exception
CallerRunsPolicyOnly use the thread of the caller to run the task
DiscardOldestPolicyA task at the head (oldest) of the queue is discarded and the current task is executed.
DiscardPolicyAbandon the current task.
 RejectedExecutionHandler rejected = null;
    rejected = new ThreadPoolExecutor.AbortPolicy();//By default, when the queue is full and the task is lost, an exception is thrown
    rejected = new ThreadPoolExecutor.DiscardPolicy();//It is not abnormal to lose tasks when the queue is full
    rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//Delete the task that entered the queue first, and then try to join the queue
    rejected = new ThreadPoolExecutor.CallerRunsPolicy();//If adding to the thread pool fails, the main thread will execute it by itself

The execution process of the thread pool?

  1. The main thread submits tasks to the thread pool. If the current number of threads is less than the number of core threads, create a new thread to execute the task. If not, go to the next step.
  2. At this time, the core thread is full, and then judge whether the number of threads stored in the work queue is full, if not, put it into the work queue, if not, go to the next step.
  3. At this time, the work queue is full, and then check whether the current number of threads is equal to the maximum number of threads, if yes, implement the rejection strategy, if not, create a new thread, and execute the task.

Configure the maximum number of threads in the thread pool

  • cpu-intensive maximumPoolSize = n*cpu + 1
  • io-intensive maximumPoolSize = 2 * n * cpu

Closing the thread pool

A thread pool can be shut down by calling the thread pool's shutdown or shutdownNow method.
The same point: traverse all worker threads, and then interrupt the threads
The difference: After shutdown is called, no new tasks will be accepted, but it will wait for the running threads and stop the threads that are not executing tasks.
When shutdownNow is called, it attempts to stop the thread that is running or suspends the task.

It's not easy to be original, please give me a thumbs up and go!

This article is written by mdnice Multi-platform publishing

Tags: Back-end

Posted by Moron on Sun, 12 Feb 2023 12:17:44 +1030