1、线程复用;
2、控制最大线程数;
3、管理线程
/**
* 创建单线池化的的线程池newSingleThreadExecutor
*/
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "获取池连接");
System.out.println(Thread.currentThread().getName() + "释放池连接");
});
}
查看下newSingleThreadExecutor底层源码
本质上还是去创建一个ThreadPoolExecutor 只是把corePoolSize 和maximunPoolSize 都设置为1
采用的是LinkedBlockingQueue 阻塞队列
/**
* 创建定长的线程池newFixedThreadPool
*/
ExecutorService executor = Executors.newFixedThreadPool(5);//创建拥有五个线程的线程池
for (int i = 0; i < 50; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "获取池连接");
System.out.println(Thread.currentThread().getName() + "释放池连接");
});
}
这里corePoolSize 和maximunPoolSize 相等于传进来的参数
上面两种采用的都是阻塞队列LinkedBlockingQueue
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);//这里这么大 控制不好容易OOM
}
/**
* 3、可缓存的线程池,空闲则回收,忙则新建线程 newCachedThreadPool
* 动态的增加缩减线程数量
*/
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "获取池连接");
System.out.println(Thread.currentThread().getName() + "释放池连接");
});
}
查看下他的底层实现
底层采用的是SynchronousQueue
当线程空闲60s就回收
1、corePoolSize :线程池中的常驻核心线程数
2、maximumPoolSize :线程池能够容纳同时执行的最大线程数,此数值必须大于等于1
3、keepAliveTime :多余的空闲线程的存活时间。当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,多余空闲线 程会被销毁直到只剩下corePoolSize个线程为止
4、unit: keepAliveTime的单位
5、workQueue :任务队列,被提交但尚未被执行的任务
6、.threadFactory:表示,生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可
7、handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数时,如何来拒绝
1、创建线程池后,等待提交过来的任务请求
2、当调用execute()方法添加一个请求任务时,线程会作如下判断:
1、如果正在运行的线程数量小于corePoolSize,那么马上分配线程运行这个任务;
2、如果正在运行的线程数量大于或等于corePoolSize,那么这个任务将进入等待队列;
3、如果这时队列满了且正在运行的线程数量还是小于maximumPoolSize,那么还是要创建非核心线程立即运行这个任务
4、 如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行
3、当一个线程完成任务时,他会从队列中取下一个任务来执行
4、一个线程无事可做超过一定的时间keepAliveTime时,线程池会判断:
如果当前运行的线程数量超过corePoolSize,那么这个线程就会被停掉
所以线程池的所有任务完成后最终会收缩到corePoolSize的大小
注意点:从corePoolSize扩充到maximumPoolSize,创建的非核心线程是分配给当前到达的任务,而不是队列中
当非核心线程达到空闲时间,则会被线程池回收