常规写多线程的弊端:
一.概念引入
线程池是一种池化技术、一种多线程处理形式,用于管理和复用一组预先创建好的线程
基本概念包括:
- 线程池:预先创建的一组线程,用于执行提交给它的任务。
- 任务队列:用于存储等待执行的任务。
- 线程管理:控制线程的创建、销毁以及线程的数量。
二. 核心原理
① 创建一个池子,池子中是空的
②提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可
③但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待
注意: 第一个并不是真正意义上没有上限,底层其实是int的最大值
public class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+".--”);
}
}
//1.获取线程池对象ExecutorService poo11=Executors.newCachedThreadPool();
//2.提交任务
pool1.submit(new MyRunnable());
Thread.sleep( millis: 1000);
pool1.submit(new MyRunnable());Thread.sleep( millis:1080);
pool1.submit(new MyRunnable());Thread.sleep( millis: 1080);
pool1.submit(new MyRunnable());Thread.sleep( millis:1080);
pool1.submit(new MyRunnable());Thread.sleep( millis:1000);
poo11.submit(new MyRunnable());
可以看到有复用的效果:
三.自定义线程池
ExecutorService newCachedThreadPool(): 创建一个可缓存线程池,可灵活的去创建线程,并且灵活的回收线程,若无可回收,则新建线程。
ExecutorService newFixedThreadPool(int nThreads): 初始化一个具有固定数量线程的线程池
ExecutorService newSingleThreadExecutor(): 初始化一个具有一个线程的线程池
//做完一个,再做一个,不停歇,直到做完,老黄牛性格
ScheduledExecutorService newSingleThreadScheduledExecutor(): 初始化一个具有一个线程的线程池,支持定时及周期性任务执行
//按照固定的计划去执行线程,一个做完之后按照计划再做另一个
其中有七个参数,我们以一个故事引入:
情况一:当我们提交三个任务时,会创建三个线程去处理
情况二:当我们提交5个任务
- 会创建三个线程处理三个任(因为只有三个核心线程),剩下的两个会加入到队列排队等待,等有了空闲的线程才会被执行
情况三:提交更多任务,比如八个
- 首先会创建三个线程执行三个任务(因为只有三个核心线程)
- 假设我们定义的队伍长度是三,那会将另外三个任务加入到队列排队等待,那剩下的两个,此时线程池会创建两个临时线程去处理执行(也就是只有当核心线程都在忙,队伍也排满了,才会创建)
情况四 :提交的任务超过核心线程+临时线程+队伍长度(以10个任务为例子,队伍长度是3)
- 首先还是会创建三个核心线程去处理三个任务
- 然后将另外三个任务加入到队列排队等待
- 继续创建临时线程去执行三个任务
- 剩下最后一个则会触发任务拒绝策略
代码演示:
四.线程池的大小
1.线程池设置为多大合适呢?
最大并行数:比如4核心8线程,就是可以同时最多可以去做8件事