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 two main methods for creating thread pools in JAVA. One is that 通过Executors工厂类提供的方法this class provides 4 different thread pools for use. The other is by ThreadPoolExecutor类making a custom creation.

Executors factory class


// 五种线程池:
//     ExecutorService threadPool = null;
//     threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
//     threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
//     threadPool = Executors.newScheduledThreadPool(2); // 具有延时,定时功能
//     threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
//     threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多   

private static void createCachedThreadPool() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            executorService.execute(() -> {
                // 获取线程名称,默认格式:pool-1-thread-1
                System.out.println(DateUtil.now() + " " + Thread.currentThread().getName() + " " + index);
                // 等待2秒
                sleep(2000);
            });
        }
    }

ThreadPoolExecutor类

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

public ThreadPoolExecutor(int corePoolSize, // 核心线程数
                              int maximumPoolSize, // 最大工作线程
                              long keepAliveTime, // 存活时间,线程没有任务执行时最多保持多久时间会终止。
                              TimeUnit unit, // 时间单位
                              BlockingQueue<Runnable> workQueue, // 工作队列
                              ThreadFactory threadFactory, // 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。
                              RejectedExecutionHandler handler // 拒绝策略,当创建新线程使线程数大于最大线程的情况下,会执行
                              )
 
{
        // 省略...
    }

The main parameters of the thread pool

  • corePoolSize The 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 FIFO queue, bounded workQueue = new LinkedBlockingQueue<>();//Linked list-based FIFO queue, unbounded workQueue = new SynchronousQueue< >();//unbuffered waiting queue, unbounded

  • threadFactory thread factory 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 拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。
参数 描述
AbortPolicy 拒绝并抛出异常
CallerRunsPolicy 只用调用者所在线程来运行任务
DiscardOldestPolicy 抛弃队列头部(最旧)的一个任务,并执行当前任务。
DiscardPolicy 抛弃当前任务。
 RejectedExecutionHandler rejected = null;
    rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
    rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
    rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
    rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行

线程池的执行过程?

20230211161701
20230211161701
  1. 主线程提交任务到线程池,如果当前线程数小于核心线程数,创建新的线程用于执行任务,如果不是,下一步。
  2. 此时核心线程已满,再判断工作队列存放的线程数是否满了,如果没有满,则放入工作队列,如果不是,下一步。
  3. 此时工作队列满了,再看当前线程数是否等于最大线程数,如果是的话,执行拒绝策略,如果不是,创建新的线程,执行任务。

配置线程池最大线程数

  • cpu密集型 maximumPoolSize = n*cpu + 1
  • io密集型 maximumPoolSize = 2 * n * cpu

线程池的关闭

可以通过调用线程池的 shutdownshutdownNow 方法来关闭线程池。 相同点:遍历所有的工作线程,然后interrupt掉线程 不同点:shutdown 调用后,不再接受新的任务,但是会等待正在运行的线程,停止没有执行任务的线程shutdownNow 调用后会尝试停止正在运行或暂停任务的线程

原创不易,麻烦点个赞​再走呗!

本文由 mdnice 多平台发布

Guess you like

Origin blog.csdn.net/ZHUXIUQINGIT/article/details/128991281