博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发编程JUC源码学习之ThreadPoolExecutor
阅读量:4214 次
发布时间:2019-05-26

本文共 3382 字,大约阅读时间需要 11 分钟。

 ThreadPool的优点,比如资源的控制以及不用频繁的创建线程等就不用多说了。主要来讨论一下ThreadPoolExecutor的几个关键参数以及对task的添加以及线程的管理。它有这么个重要的参数corePoolSize、maximumPoolSize、keepAliveTime和taskqueue。

corePoolSize   线程池维持处于Keep-alive状态的线程数量。如果设置了allowCoreThreadTimeOut为true,该值可能为0。
maximumPoolSize   线程池中可维持线程的最大值。
keepAliveTime   当线程池中线程数量大于
 corePoolSize  时,如果某些线程的空闲时间超过该值就会终止,直到线程数小于等于corePoolSize。
    1. 添加一个task的过程
    当要添加一个新的task,如果当前线程数小于
 corePoolSize,直接添加一个线程,即使当前有空闲的线程。否则添加队列中。如果队列满了呢?则会判断当前线程数是否小于maximumPoolSize,如是则添加一个新的线程用来执行该task。如果超出最大线程数,那就只能reject了。
       
int c = ctl.get();        // 当前线程数小于corePoolSize        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);            else if (workerCountOf(recheck) == 0)                addWorker(null, false);        }       //队列满时添加新的线程,如果线程数超过maximumPoolSize则reject        else if (!addWorker(command, false))            reject(command);
 
     使用addWorker(),来创建新的线程并传入的task作为第一个task执行。由此来看只有队列满时才会创建大于corePoolSize的线程。
 
    2.   KeepAliveTime是如何实现的呢?
       keepAliveTime的职责时,当线程池的队列满了,创建了多于corePoolSize的线程,这时处于节省资源的目的,会杀死多于corePoolSize空闲时间大于keepAliveTime的线程。它是如何做到呢?我们知道Woker时从taskQueue不断地轮询获取task并执行。如果获取不到task取到null时则退出循环结束线程。大概源码是这样的。
     
try {           //当取到task为null,跳出循环结束线程            while (task != null || (task = getTask()) != null) {                w.lock();                clearInterruptsForTaskRun();                 //此处省略,主要是执行task.run             }
 
      关键是看看getTask()如何返回null,该方法的comments列出几种返回null并减少当前线程数的情景。我们在这里只关心keeAliveTime的实现。
      
boolean timedOut = false; // Did the last poll() time out? 该变量标识从taskqueue中取任务是否超时,如果超时则返回null         retry:        for (;;) {            int c = ctl.get();            int rs = runStateOf(c);            // Check if queue empty only if necessary.            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {                decrementWorkerCount();                return null;            }            boolean timed;      // Are workers subject to culling?            for (;;) {                int wc = workerCountOf(c);                timed = allowCoreThreadTimeOut || wc > corePoolSize;//线程数大于corePoolSize满足了杀死空闲线程的条件                //第一次执行到这里,由于timeOut为false,跳出内循环执行从queue取任务                if (wc <= maximumPoolSize && ! (timedOut && timed))                    break;                //第二次执行的时候由于timedOut为true,不会跳出内循环。执行下面的代码               //将当前线程数减1并返回null致使该线程终止                if (compareAndDecrementWorkerCount(c))                    return null;                c = ctl.get();  // Re-read ctl                if (runStateOf(c) != rs)                    continue retry;                // else CAS failed due to workerCount change; retry inner loop            }            try {               //timed为true,这段code是实现空闲时间超过keepalivetime就被终止的精华所在。              // 在给定的keepalivetime时间内从阻塞队列中取任务。如timeout则返回null                Runnable r = timed ?                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :                    workQueue.take();                if (r != null)                    return r;                timedOut = true;//如从queue中取任务超时则为true            } catch (InterruptedException retry) {                timedOut = false;            }        }
 

转载地址:http://jqdmi.baihongyu.com/

你可能感兴趣的文章
hdoj 1180 搜索 + bfs + 优先队列
查看>>
hdoj 2141 二分 + 优化
查看>>
PAT 天梯赛 L1-027. 出租 (简单字符串处理)
查看>>
hdoj 1863 最小生成树(kruskal + 并查集)
查看>>
hdoj 1001 水题坑人 小心
查看>>
康拓展开
查看>>
二叉堆 删除 插入 调整 堆排序
查看>>
hdoj 1874 单源最短路径
查看>>
hdoj 2544 最短路径 dijkstra + 优先队列
查看>>
同余定理 + 快速幂
查看>>
计算几何初步
查看>>
NYOJ 33蛇形填数
查看>>
常用快捷键
查看>>
Wifi列表获取遇到的问题
查看>>
后端:搭建服务器
查看>>
Android 通过Web服务器与Mysql数据库交互
查看>>
2012(第三届)预赛第四题
查看>>
蓝桥杯2012(第三届)(分段乘法)
查看>>
蓝桥杯2012(第三届)第八题
查看>>
CSP 2017_12_4行车路线
查看>>