线程池
池化思想:线程池,字符串常量池,数据库连接池
提高资源的利用率
普通线程
1,手动创建线程对象(买手机)
2,执行任务(打电话)
3,执行完毕,释放线程对象(扔手机)
线程池
1,激活已经创建好的核心线程(从口袋里拿手机)
2,执行任务(打电话)
3,收回线程(放回口袋里,当需要使用时再拿出来)
线程池的优点:
提高线程的利用率
提高程序的响应速度 (线程对象是提前创建好的,并且使用完成之后不会销毁)
便于统一管理线程对象
可以控制最大的并发数 (通过设置线程池的参数来控制线程池的容量,进而控制系统的最大并发量)
此时有四位客户来银行柜台办理业务,但是只开启了三个窗口(3个核心线程),所以会让第四位顾客到等待区( ArrayBlockingQueue 等待队列)等待直到有空余窗口才能去办理业务
当顾客过多,等待区被挤满时,会开启临时窗口(启用临时线程)
注:在等待区外的顾客会直接到新开启的窗口办理业务,无需进入等待区等待
拒绝策略
当所有窗口和等待区都被挤满,那么会采用拒绝策略(handler),就不准备接收多余客的户让他走
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(
//corePoolSize 核心线程数(3个柜台窗口号)
3,
//maximumPoolSize 最大线程数(最多有5个柜台窗口)
5,
//keepAliveTime 存活时间(柜台4号,5号的上班时长)
1,
//unit 存活时间的时间单位(柜台4号,5号上班的时长的时间单位)
TimeUnit.SECONDS,
//等待队列 ArrayBlockingQueue<>(等待区长度)
new ArrayBlockingQueue<>(3),
//threadFactory 线程工厂
Executors.defaultThreadFactory(),
//handler 拒绝策略(使用了抛异常的策略)
new ThreadPoolExecutor.AbortPolicy());
/**
* i 客户数量
*/
for (int i = 0; i < 4; i++) {
executorService.execute( ()->{
System.out.println(Thread.currentThread().getName() + "====>办理业务");
});
}
executorService.shutdown();
}
运行结果: