今天同事突然提出问题说用哪个线程池好,newFixedThreadPool和newCacheThreadPool里选择,说固定大小线程池keepAliveTime=0,线程空闲会立马回收线程从而节约资源,然后另外一个同事说,0是代表永远不回收,我记忆里也是记得0是永久存活,因为网上很多博客啊,资料啊都是说的0表示线程永久存活在空闲的时候。前面那位同事也是从字面上认为的,没有经过验证,觉得-1才是永久不回收,然后各自进行了一波研究分析。

经过看源码,发现keepAliveTime<0是不行的,直接报错,也就是同事的猜测-1才是不回收 是错误的,看下面代码图示(别问我怎么给代码里部分标红,直接用浏览器F12自己编辑页面写标签样式进去的。。)

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
然后找keepAliveTime的使用一时半会也没找到,就用代码测试了,发现设置keepAliveTime=0核心线程数确实没有回收,后面同事说在并发病程的艺术那本书上有一段描述

“当线程池中的线程数大于corePoolSize时,keepAliveTime为多余的空闲线程等待新任务的 最长时间,超过这个时间后多余的线程将被终止。这里把keepAliveTime设置为0L,意味着多余 的空闲线程会被立即终止。”

同事又开始迷茫了,我一开始没细看,觉得说的不对,后面反复阅读,发现这段文字描述的是说keepAliveTime控制的是非核心线程数的回收,也就是0的时候,非核心线程数会在空闲的时候回收,并不是说核心的会回收。

为了验证结果,我们就用代码进行了测试,测试代码如下:

package com.xhs.concurrent.threaddemo.sync;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
/**
 * @author xuhan  build  2019/4/23
 */
public class ExecutorsDemo implements Runnable{
 
    private int i=0;
 
    public ExecutorsDemo(int i) {
        this.i = i;
    }
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1,2,0, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1));
        for(int i=0;i<3;i++){
            executor.execute(new ExecutorsDemo(i));
        }
        while(true){
            System.out.println("总线程数:"+executor.getPoolSize()+"当前活跃线程数:"+executor.getActiveCount());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public void run() {
        System.out.println("i="+i+" Thread = "+Thread.currentThread().getName());
        if(i>=1){
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println("i="+i+" sleep 1 s结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println("i="+i+" sleep 3 s结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
设置核心线程数和非核心线程数分别为1个,队列容量为1,进入3个runnable:

第一个创建主线程,第二个进入队列,第三个则创建非主线程运行,

输出结果为

i=0 Thread = pool-1-thread-1
i=2 Thread = pool-1-thread-2
总线程数:2当前活跃线程数:2
总线程数:2当前活跃线程数:2
i=2 sleep 1 s结束
i=1 Thread = pool-1-thread-2
总线程数:2当前活跃线程数:2
总线程数:2当前活跃线程数:2
i=1 sleep 1 s结束
总线程数:1当前活跃线程数:1
总线程数:1当前活跃线程数:1
i=0 sleep 3 s结束
总线程数:1当前活跃线程数:0
可以看到非核心数线程执行完毕之后,队列中的task进入继续执行,等再次进入队列的task结束后,可以看到总线程数减少了1,而等核心线程执行完毕后,发现总线程数没有减少,但活跃线程数减少,也就是核心线程数没有回收。书上说的是正确的,大部分网上的博客说的keepAliveTime=0永久不回收是有出入的。

如果要设置核心线程的回收,则需要设置

executor.allowCoreThreadTimeOut(true);
但这是keepAliveTime必须要>0才行,否则会抛出异常!!!

throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
如果看了之后觉得有问题,希望各位指点一番!!谢谢!!
————————————————
版权声明:本文为CSDN博主「xuhangsong」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xuhangsong/article/details/89474989

ava线程池ThreadPoolExecutor的keepAliveTime=0时,表示超过core线程数的线程在空闲时立即结束相关推荐

  1. 并发编程(七)好用的线程池ThreadPoolExecutor

    并发编程专栏系列博客 并发编程(一)python并发编程简介 并发编程(二)怎样选择多线程多进程和多协程 并发编程(三)Python编程慢的罪魁祸首.全局解释器锁GIL 并发编程(四)如何使用多线程, ...

  2. python线程池wait_python线程池 ThreadPoolExecutor 的用法示例

    前言 从Python3.2开始,标准库为我们提供了 concurrent.futures 模块,它提供了 ThreadPoolExecutor (线程池)和ProcessPoolExecutor (进 ...

  3. Python 线程池 ThreadPoolExecutor(一) - Python零基础入门教程

    目录 一.Python 线程池前言 二.Python 线程池原理 三.Python 线程池 ThreadPoolExecutor 函数介绍 四.Python 线程池 ThreadPoolExecuto ...

  4. java 线程池ThreadPoolExecutor

    线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根 据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数 ...

  5. Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

    为什么80%的码农都做不了架构师?>>>    这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情.并发课题对于Java来说是一个又重要又难的一大块 ...

  6. Java并发—线程池ThreadPoolExecutor基本总结

    原文作者:Matrix海子 原文地址:Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线 ...

  7. Java线程池ThreadPoolExecutor

    2019独角兽企业重金招聘Python工程师标准>>> 本文首发于个人微信公众号<andyqian>, 关注免费获取Java学习资料 前言 多线程一直是Java进阶的必修 ...

  8. Java线程池ThreadPoolExecutor的实例

    Java.util中的线程池和Spring框架对这个类的扩展 1.单独通过java里的ThreadPoolExecutor这个类,可以创建线程池,如果系统采用Spring框架设计,可以采用Thread ...

  9. Java—这把线程池ThreadPoolExecutor操作,你学会了吗?

    关注微信公众号:CodingTechWork,一起学习进步. 引导 要求:线程资源必须通过线程池提供,不允许在应用自行显式创建线程: 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资 ...

最新文章

  1. python在中小学教学中的应用-在python程序中的进程操作
  2. ffmpeg命令行map参数的使用
  3. webx3 日志系统级别问题
  4. 某考试 T2 Tree
  5. OpenShift 之 用CodeReady Workspaces开发Quarkus云原生应用
  6. 《iOS应用安全攻防实战》第六章:无法销毁的文件
  7. ERROR: CMake must be installed to build dlib
  8. shell中find某个文件排除某个目录
  9. java 组件更新,java – 我可以批量处理一些Swing组件更新,以便重绘全部一次完成吗?...
  10. 高科技应用之人脸识别、,
  11. LineageOS的代码下载、编译及真机运行
  12. 七夕怕被偷窥?摄像头探测器来帮您!
  13. 剑指offer: 两个栈实现一个队列
  14. android红米升级失败怎么办,红米刷机失败怎么办?解决红米刷机失败教程
  15. 橙色——网页效果图设计之色彩索引
  16. CyanogenMod 7
  17. 万兴剪刀手去水印教程_万兴神剪手怎么去水印教程_赶快收藏吧
  18. P1335 [NOI2013] 小Q的修炼 题解
  19. 视频像素数据_从摄像头到驱动
  20. cadence SPB17.4 - allegro - 尺寸标注

热门文章

  1. Mysql可重复读实现原理分析
  2. android按钮防止重复点击事件,实例详解Android解决按钮重复点击问题
  3. ensp小实验走起来(路由下发、MSTP、VRRP、DHCP、DHCP中继、NAT、链路聚合)之配置
  4. jet mysql连接字符串,关于jet db的连接字串,以及加密后的字串-数据库专栏,SQL Server...
  5. visual studio 怎么生成coredump文件_coredump详解
  6. python 保存网页到印象笔记_如何将网页内容保存到印象笔记?
  7. linux逻辑分区最小值,linux 逻辑卷管理 调整分区大小
  8. 2019计算机考研在职研究生,2019双证在职研究生报名条件
  9. (2) 用java实现一个简易编译器1-词法解析入门
  10. 关于举办XX学院“XX杯”网页设计大赛的通知