![3dc274ad625eaca1d060a469da549602.png](https://img-blog.csdnimg.cn/img_convert/3dc274ad625eaca1d060a469da549602.png)
很早之前就看过线程池源码(知道大概的运行原理),但是只是知道怎么用,并没有深究。这次为了帮助自己深入理解线程池,决定手动写一个极简(陋)的线程池,顺便记录思考和造轮过程。
虽然不太可能和jdk自带的那么完美,但是该有的功能还是要有:
新建线程池,有核心线程数和最大线程数,线程存活时间,队列
在线程池加入线程,当前线程数不超过核心线程数就新建线程,超过核心放队列,队列满了再新建线程,达到最大线程
全部线程运行完成后会保留核心线程数,支持线程存活时间
立即关闭线程池
优雅的关闭线程池
1.新建一个轮子线程池类,就一个构造函数,把需要的参数都传进来
![89944ebb8c00b88066d9e1d5e7a391a4.png](https://img-blog.csdnimg.cn/img_convert/89944ebb8c00b88066d9e1d5e7a391a4.png)
2.用ThreadPoolExecutor的时候,新建了线程池就会往里面提交线程了,我们写的也一样,而且往线程池里面加线程的时候就会判断:当前运行线程数是否大于核心线程数,是否大于最大线程数等,这里需要一个当前运行线程数的变量。
所以这里增加一个成员变量activeCount,初始值为0,运行一个线程就加1,线程运行结束就减1,这里面减的时候是在不同线程里面,所以为了线程安全用AtomicInteger类型
/** 当前活动线程数 */ private AtomicInteger activeCount = new AtomicInteger(0);
提交线程的方法,看过ThreadPoolExecutor源码的应该知道,里面每个线程都是包装了一个Worker类,新增线程的时候就会新建一个worker,为什么要这么做呢? 我第一次看的时候也不理解,想着如果直接把传进来的线程start一下怎么样,如果直接新建线程会立马就发现问题,怎么知道线程什么运行完,怎么把activeCount减1? 所以这里不能直接start,必须新建一个线程(异步执行,废话),这个线程必须要运行参数的线程run方法(废话,不然参数还有啥用,我们的业务逻辑咋执行),线程运行完成后activeCount减1。
所以这里有了worker类,worker本身也是一个线程。顺便把线程名字也解决了,新建一个threadNum从0开始,新建一个worker就+1
![b270d8321ac1e5bff1e693c307cfb37f.png](https://img-blog.csdnimg.cn/img_convert/b270d8321ac1e5bff1e693c307cfb37f.png)
提交线程
![d83dcce6cb6223437efb7936cd4d98c0.png](https://img-blog.csdnimg.cn/img_convert/d83dcce6cb6223437efb7936cd4d98c0.png)
3.现在已经有点样子了,但是问题还很多,主要的一个问题:比如我建一个core=2,max=5,queue=5的线程池,假设往里面放了8个线程,会出现只运行了3个线程,跑完也就结束了,剩下的5个会在队列里面没处理,而且也不会保留2个核心线程
![b2eb41fc2dd2553a9f024166234f17c6.png](https://img-blog.csdnimg.cn/img_convert/b2eb41fc2dd2553a9f024166234f17c6.png)
WheelThreadPool2的运行结果
![7f417856c6762b086e9c1c86204f6358.png](https://img-blog.csdnimg.cn/img_convert/7f417856c6762b086e9c1c86204f6358.png)
现在想想怎么把队列的线程拿出来运行,没看ThreadPoolExecutor源码前我第一次想着是不是在创建线程池的时候默认启动一个线程去队列里面获取并执行,然而一想立马否定了,因为线程池是多线程运行的,队列里面的线程需要max(参数最大线程数)个线程同时执行。 所以在我们新建的worker里面要能不断的循环获取队列的线程去执行,如果队列为空了,则退出循环,让线程结束
改造一下worker的run方法,在execute方法创建的worker线程执行完通过参数传进来的runnable之后,循环获取队列并执行队列线程的run方法