JDK线程池源码浅析

出于功利的原因,很早之前就想搞清楚JDK线程池的原理,在工作不到一年的时候就点进源码去看了看,当然没看不懂。
后来搜索了多篇文章来读,看得模模糊糊。现在想起来,一点印象都没有。
今天看了一篇老文章,温故知新,给了我很大启发,借此谈谈怎样阅读源码。

  1. 源码并不神秘,虽然看起来复杂,但其规律是能被把握的。
  2. 源码不是看懂的,哪怕你用再多的时间。除了分析,还必须实践,否则徒劳无功。
  3. 想要用一大块完整的时间来看懂源码,是不现实的。因为对复杂事务的认知是分层次的,需要分清主次深浅。循序渐进,反复迭代,每次弄懂一小块,做好记录,迭代久了才可能有深入认知。切忌急躁贪功。
  4. 源码不必全部看懂,全看了也未必有益,但大体上能看出粗象,不然无法表达。
  5. 任何软件的初衷都是简单的,但随着迭代衍化,逻辑逐步变得庞大复杂。要学会忽略枝叶,看到主干,否则将陷入无穷的细节中。

现在回到线程池,可以归结为几个重要问题:

  1. ThreadPoolExecutor有哪些参数?有什么意义?
    corePoolSize: 核心线程数量,可以类比正式员工数量,常驻线程数量。
  • maximumPoolSize: 最大的线程数量,常驻+临时线程数量。
  • workQueue:多余任务等待队列
  • keepAliveTime:非核心线程空闲时间,就是外包人员等了多久,如果还没有活干,解雇了。
  • threadFactory: 创建线程的工厂,在这个地方可以统一处理创建的线程的属性。每个公司对员工的要求不一样,恩,在这里设置员工的属性。
  • handler:线程池拒绝策略,什么意思呢?就是当任务实在是太多,人也不够,需求池也排满了,还有任务咋办?默认是不处理,抛出异常告诉任务提交者,我这忙不过来了。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

高3位表示线程池状态(一共5种),低29位表示线程数量。

  1. ThreadPoolExecutor 中的线程和普通线程有哪些不同之处?
private final class Worker  extends AbstractQueuedSynchronizer implements Runnable
  1. ThreadPoolExecutor 中的线程放在什么容器内?
    /**
     * Set containing all worker threads in pool. Accessed only when
     * holding mainLock.
     */
    private final HashSet workers = new HashSet();
    private final ReentrantLock mainLock = new ReentrantLock();
  1. ThreadPoolExecutor 中的多余的空闲线程怎样消失?
        try {
            while (task != null || (task = getTask()) != null) {
                // do sth

            }
        } finally {
            processWorkerExit(w, completedAbruptly); // 从works中删除
        }

getTask()是关键方法,核心代码:

int wc = workerCountOf(c);
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
Runnable r = timed ?   workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) :
                    workQueue.take();
if (r != null)
        return r;

这里只是粗略介绍一下,但是有了这点知识,就大概能有一个轮廓。
至于深入细节……

鸣谢:深入源码分析Java线程池的实现原理

你可能感兴趣的:(JDK线程池源码浅析)