Java中的ThreadPoolExecutor线程池原理细节解析

 更新时间:2023年12月27日 10:35:08   作者:笑我归无处  
这篇文章主要介绍了Java中的ThreadPoolExecutor线程池原理细节解析,ThreadPoolExecutor是一个线程池,最多可使用7个参数来控制线程池的生成,使用线程池可以避免创建和销毁线程的资源损耗,提高响应速度,并且可以管理线程池中线程的数量和状态等等,需要的朋友可以参考下

一、什么是ThreadPoolExecutor

ThreadPoolExecutor是一个线程池,最多可使用7个参数来控制线程池的生成。 使用线程池可以避免创建和销毁线程的资源损耗,提高响应速度,并且可以管理线程池中线程的数量和状态等等。 阿里巴巴手册中也推荐使用该线程池,因为Executors创建缓存线程池时,最大线程数是Integer.MAX_VALUE,可能导致堆栈溢出。而且使用ThreadPoolExecutor创建线程池可以让开发者更好理解线程池原理。

二、使用线程池的优点

1.减少系统资源消耗

无须重复创建和销毁线程,减少了线程创建和销毁造成的资源消耗。

2.提高响应速度

创建好的线程会驻留在线程池中,无需创建新线程执行任务,因而提高了响应速度。

3.提高了线程的可管理性。

线程池可以控制线程的数量,可以选择拒绝策略,可以监控和管理线程的状态,控制并发量等等。 这些都是自己创建线程难以做到的。

三、线程池原理

3.1 线程池的7个参数

1)corePoolSize 核心线程数

线程池常驻线程数量

2)maximumPoolSize 最大线程数

最大可存在的线程数量

3)keepAliveTime 非核心线程的存活时间

非核心线程空闲时,可以停留的时间

4)unit 存活时间的单位

非核心线程空闲时,可以停留的时间的单位

5)workQueue 阻塞队列

线程都在使用中时,可以将任务保存在阻塞队列中,可以设置队列的长度。

6)threadFactory 线程创建工厂

可以选择创建线程的工厂

7)handler 拒绝策略

当线程池无法存放更多任务时,处理这些过多的任务的策略

3.2 线程池执行任务的流程

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    //判断工作线程数是否小于核心线程数
    if (workerCountOf(c) < corePoolSize) {
    	//是,创建一个新线程
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //否,将任务尝试添加到阻塞队列中,如果队列满了则会添加失败。
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //判断线程池状态是否在运行中,不在运行中时,删除该任务
        if (! isRunning(recheck) && remove(command))
        	//不在运行中时,执行拒绝策略
            reject(command);
        //判断工作线程数是否为0
        else if (workerCountOf(recheck) == 0)
        	//为0的场合,尝试创建新线程
            addWorker(null, false);
    }
    //添加失败的场合,尝试创建一个新线程
    else if (!addWorker(command, false))
    	//如果添加失败,执行拒绝策略
        reject(command);
}
  1. 当执行一个任务时,首先会判断工作线程数是否小于核心线程数。
    • 如果小于核心线程数,则创建一个新线程来执行该任务。执行完毕。
  2. 如果大于核心线程数,则尝试将任务放入阻塞队列中。
    • 如果成功放入阻塞队列,待有空闲的线程时,空闲线程会从阻塞队列中获取任务并执行。执行完毕。
  3. 如果放入失败,表示阻塞队列已满,此时会尝试创建一个新线程来执行该任务。
    • 如果当前线程数小于最大线程数,则会创建新线程来执行该任务。执行完毕。
    • 如果工作线程数等于最大线程数,则不会创建新线程,尝试创建失败。此时会执行拒绝策略。执行完毕。

四、Executors提供的常用线程池

4.1 Executors.newFixedThreadPool

一个固定数量的线程池,可以通过传入的参数int nThreads来控制线程池的线程数量。(核心线程数和最大线程数相同)

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

4.2 Executors.newSingleThreadExecutor

一个线程数只有1的线程池。可以保证任务的顺序执行。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

4.3 Executors.newCachedThreadPool

缓存线程池,新创建的线程会在该线程池中缓存60秒。可以提高短期异步任务的性能。 注意,最大线程数是Integer.MAX_VALUE,高并发的场合下,可能会创建大量线程。

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

4.4 Executors.newScheduledThreadPool

定时任务线程池,使用该线程池可以定时执行任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

到此这篇关于Java中的ThreadPoolExecutor线程池原理细节解析的文章就介绍到这了,更多相关ThreadPoolExecutor线程池原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • EasyExcel动态表头基础用法及最佳实践详解

    EasyExcel动态表头基础用法及最佳实践详解

    EasyExcel是阿里巴巴开源的一个基于Java的简单、省内存的读写Excel工具,在处理大量数据时,它能极大地减少内存占用提高性能,这篇文章主要介绍了EasyExcel动态表头基础用法及最佳实践的相关资料,需要的朋友可以参考下
    2026-03-03
  • Java AQS的实现原理详解

    Java AQS的实现原理详解

    这篇文章主要借助了ReentrantLock来带大家搞清楚AQS的实现原理,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-04-04
  • IDEA调试功能使用总结(step over/step into/force step into/step out)

    IDEA调试功能使用总结(step over/step into/force step into/step o

    本文主要介绍了IDEA调试功能使用总结(step over/step into/force step into/step out),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • JavaWeb表单注册界面的实现方法

    JavaWeb表单注册界面的实现方法

    这篇文章主要介绍了JavaWeb表单注册界面的实现方法的相关资料,希望通过本文大家能掌握这部分内容,需要的朋友可以参考下
    2017-09-09
  • Spring boot整合Mybatis-plus过程解析

    Spring boot整合Mybatis-plus过程解析

    这篇文章主要介绍了Spring boot整合Mybatis-plus过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • java 通过 SmbFile 类操作共享文件夹的示例

    java 通过 SmbFile 类操作共享文件夹的示例

    这篇文章主要介绍了java 通过 SmbFile 类操作共享文件夹,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • pagehelper分页工具类的封装

    pagehelper分页工具类的封装

    这篇文章主要为大家详细介绍了pagehelper分页工具类的封装,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • java 实现web项目启动加载properties属性文件

    java 实现web项目启动加载properties属性文件

    这篇文章主要介绍了java 实现web项目启动加载properties属性文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • JAVA 多态操作----父类与子类转换问题实例分析

    JAVA 多态操作----父类与子类转换问题实例分析

    这篇文章主要介绍了JAVA 多态操作----父类与子类转换问题,结合实例形式分析了JAVA 多态操作中父类与子类转换问题相关原理、操作技巧与注意事项,需要的朋友可以参考下
    2020-05-05
  • Java实现grpc框架的示例

    Java实现grpc框架的示例

    本文主要介绍了gRPC框架及其与ProtocolBuffers的结合,用于构建分布式系统,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09

最新评论