问题
1、线程池的线程是如何做到复用的?
2、线程池是如何做到高效并发的?
3、线程池怎么处理线程共用参数?
3、从线程池的设计中,我们能学到什么?
源码
1、ThreadPoolExecutor
核心实现类是ThreadPoolExecutor,先看这个类的第一个成员变量ctl,AtomicInteger这个类可以通过CAS达到无锁并发,效率比较高,这个变量有双重身份,它的高三位表示线程池的状态,低29位表示线程池中现有的线程数,用最少的变量来减少锁竞争,提高并发效率。
2、execute/submit
线程池提交任务有这2种方式,execute是ExecutorService接口定义的,submit有三种方法重载都在AbstractExecutorService中定义,都是将要执行的任务包装为FutureTask来提交。此方法中没有任何同步相关逻辑。
3、addWorker(Runnable firstTask, boolean core)
execute方法虽然没有加锁,但是在addWorker方法内部,加锁了ReentrantLock,这样可以保证不会创建超过我们预期的线程数,做到了在最小的范围内加锁,尽量减少锁竞争;core参数,只是用来判断当前线程数是否超量的时候跟corePoolSize还是maxPoolSize比较,Worker本身无核心或者非核心的概念。
4、work继承AQS
主要是用来维护线程执行任务的中断控制状态,它实现了Runnable 接口同时继承了AQS,实现 Runnable 接口意味着 Worker 就是一个线程,继承 AQ