线程池
1、线程池优点
1、降低资源消耗,重复使用已经创建好的线程来减少创建和关闭线程造成的消耗
2、提高响应速度,不需要创建线程,直接就可以调用线程来执行任务
3、线程统一管理,分配,调优和监控
2、线程池都有哪些参数
1、核心线程数:允许同时执行的线程数
2、最大线程数:包含核心线程数,最多同时存在的线程数,多余的线程等待核心线程执行完后,继续执行
3、最大空闲时间:也就是执行时间,如果没有任务执行的时候,允许线程存活多久
4、时间单位:控制最大空闲时间
5、任务队列:如果核心线程数用完了,再有任务提交到线程池中时,会先加到任务队列中,如果任务队列都存不下的时候,才会继续创建线程,直到达到最大线程数就不再创建线程
6、线程工厂:允许用户使用自己创建的线程
7、饱和处理机制:当最大线程数量也满了,还有其他线程加入的情况下,会使用到饱和处理机制。
3、生活举例线程池工作原理
客户a(任务)去银行(线程池)办理业务,但银行刚开始营业,窗口服务员未上岗(相当于线程池中没有线程),于是经理安排1号员工招待客户a(创建线程执行任务)
在客户a业务还没办完的时候,客户b就来了,于是经理安排2号工作人员处理客户b的需求(创建两个核心线程),此时假设银行中只有两个核心线程(核心线程数量是2)
a,b两个客户的任务还没执行完,客户c就来了,于是经理让客户c去大厅坐着(任务队列中等待);
此时客户d也来了,任务队列中的任务数也满了,经理看窗口(核心线程)和大厅(任务队列)中的客户(任务)都满了,就又安排了临时工3号员工(最大线程数)来处理d的任务
又来了一个客户e,此时最大线程数,核心线程,大厅都满了,拒接客户e(饱和机制)
客户都走了,临时工和窗口的员工都闲下来了,超过了一个小时,于是经理让临时工下班了(销毁线程),但是核心线程即使没活了也得保持在工作岗位
4、内置线程池ExecutorService
1、常用方法
1、shutdown():执行该方法后,拒绝之后加入任务,但会执行完之前的任务
2、shutdownNow():停止所有正在执行的任务,并且返回所有中途停止的任务
3、submit(Callble task):执行一个带返回值的任务,返回一个future对象
Future<Object> submit = executorService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
int i = 0;
for (int j = 0; j < 10; j++) {
i++;
}
return i;
}
});
Object o = submit.get();
System.out.println(o); // 10
4、submit(Runnable task):提交任务
5、submit(Runnable task,T result):执行runnable任务,返回一个T result 类型的future对象
6、execute():执行runnable任务,没有返回值
6、future对象:
等待线程执行结果
get():获取返回的值
cancel():取消任务
isCancelled():任务是否正常取消
isDone():任务是否正常完成
2、Executors.newCachedThreadPool();
创建一个可空闲60秒的线程池对象,线程60秒会自动销毁,没有核心线程
3、Executors.newFixedThreadPool(10);
创建一个固定线程数的线程池,不会销毁
4、Executors.newSingleThreadExecutor();
创建一个只有一个线程的线程池
5、Executors.newScheduledThreadPool(5);
创建一个可延迟运行或者可定时运行的线程池
方法1: schedule(Runnble , delay, TimeUnit): delay时间后执行
方法2: schedule(Runnble , delay, TimeUnit): delay时间后执行
方法3: scheduleAtFixedRate(Runnable,5L,2,TimeUnit.SECONDS); 5秒后,每2秒执行一次任务,不论任务是否运行完都会到时间执行
方法5: scheduleWithFixedDelay(Runnable,5L,2,TimeUnit.SECONDS); 5秒后,每2秒执行一次任务,等待任务运行完后才会进行下次定时
6、Executors.newWorkStealingPool();
创建一个抢占式的线程池