一,线程池的参数介绍:
通过上图可知:ThreadPoolExecutor有7个参数
corePoolSize:核心线程数
- 举个简单的例子:一个奶茶店老板,在生意正火爆的时候发现正式员工人手不够了,于是他就想了个办法,在旺季多招一些临时工,等到生意淡下来了就将那些临时工辞掉,这里的正式员工就相当于是核心线程数(一旦录用,永不辞退)。
- (注意:如果在实际开发中有人问到:核心线程数设置成多少更合适,此时只要是你回答出了具体的数字,那都是错的,这个问题应该看场景,具体设置成多少要改变不同的值去调试)。
maximumPoolSize:最大线程数
- 正如上面的例子,那些实习生就相当于最大线程数(一段时间不干活就被辞退)。
keepAliveTime:临时工允许的空闲时间
- 如果临时工的空闲时间超出了这个时间就会被辞退,同理:也就是一些临时创建的线程超时了,就会被销毁。
unit:keepaliveTime 的时间单位, 是秒, 分钟, 还是其他值
workQueue:传递任务的阻塞队列
- 本质也就是存放数据的一种数据结构
我们传入的任务通过submit 调用 put 方法,使这个任务入队列。在线程执行的时候,通过take方法来从队列中取出任务。
threadFactory:创建线程的⼯⼚, 参与具体的创建线程⼯作. 通过不同线程⼯⼚创建出的线程相当于对⼀些属性进⾏了不同的初始化设置
- 可能你会有点懵,很正常,上图:
- 工厂类的定义:
- 工厂类的实现:
RejectedExecutionHandler: 拒绝策略, 如果任务量超出公司的负荷了接下来怎么处理(这也是这七个参数中最重要的一个)
- AbortPolicy(): 超过负荷, 直接抛出异常.
- CallerRunsPolicy(): 调⽤者负责处理多出来的任务.
- DiscardOldestPolicy(): 丢弃队列中最⽼的任务.
- DiscardPolicy(): 丢弃新来的任务.
通俗点来说
二,使用Executors 创建常见的线程池
Executors 创建线程池的⼏种⽅式:
- newFixedThreadPool: 创建固定线程数的线程池
- newCachedThreadPool: 创建线程数⽬动态增⻓的线程池.
- newSingleThreadExecutor: 创建只包含单个线程的线程池.
- newScheduledThreadPool: 设定 延迟时间后执⾏命令,或者定期执⾏命令. 是进阶版的 Timer.
(Executors 本质上是 ThreadPoolExecutor 类的封装)
三, 线程池的工作流程
此时我们就要模拟实现一个线程池了,步骤::
- 1)核⼼操作为 submit, 将任务加⼊线程池中
- 2)使⽤ Worker 类描述⼀个⼯作线程. 使⽤ Runnable 描述⼀个任务.
- 3)使⽤⼀个 BlockingQueue 组织所有的任务
- 4)每个 worker 线程要做的事情: 不停的从 BlockingQueue 中取任务并执⾏.
- 5)指定⼀下线程池中的最⼤线程数 maxWorkerCount; 当当前线程数超过这个最⼤值时, 就不再新增
线程了
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class MyThreadPool{//创建阻塞队列private BlockingQueue<Runnable> pool = new ArrayBlockingQueue<>(5);//写submit方法:并将对象传入阻塞队列public void submit(Runnable runnable) throws InterruptedException {pool.put(runnable);}//构造方法:当每次传入一个 n 之后,就会循环 n 次去创建 n 个线程对象,public MyThreadPool(int n){for (int i = 0; i < n; i++) {//注意:外面的for循环和里面的线程的内容是没有任何关系的,因为线程里面的内容是在另一个线程中//执行的,而for循环是在main线程中执行的。所以,要是你有一个疑问:while循环的条件不是true吗//为啥还能继续执行下一个for循环,而不是卡到这里了。原因就是他们是在不同的线程上执行的,for循环//和Thread里面的内容是没有关系的。Thread t1 = new Thread(() ->{while(true){Runnable r = null;try {r = pool.take();} catch (InterruptedException e) {throw new RuntimeException(e);}r.run();}});t1.start();}}
}
public class Demo1 {public static void main(String[] args) throws InterruptedException {//我们首先创建了4个核心线程MyThreadPool pool = new MyThreadPool(4);for (int i = 0; i < 1000; i++) {pool.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+" hellO");}});}}
}