1.线程的缺点:
(1)线程的创建需要开辟内存资源:本地方法栈、虚拟机栈、程序计数器等线程私有变量的内存。频繁的创建线程和销毁线程会带来一定的性能开销;
(2)使用线程不能很好地管理任务和有好的拒绝任务;
2.线程池
线程池:使用池化技术来管理和使用线程的技术。
3.线程池的好处
线程池的好处是减少在创建和销毁线程上锁消耗的时间以及系统资源的开销,解决资源不足的问题;如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
4.线程池的创建方式(7种):
(1)创建固定个数的线程池——Executors.newFixedThreadPool(10);——适用:任务数确定的情况;
(2)创建带缓存的线程池——Executors.newCachedThreadPool();——适用:有大量的短期任务的情况;
(3)可执行定时任务的线程池——Executors.newScheduledThreadPool(10);
- service.scheduleWithFixedDelay();——4个参数:线程池的任务,定时任务延迟多长时间开始执行,定时任务的执行频率,时间单位;——任务开始执行时间是以上次任务执行的结束时间作为开始时间的。——时间不固定,根据任务执行的时间来定。
- service.schedule() ——3个参数;
- service.scheduleAtFixedRate()——3个参数——开始时间是以上次任务的开始时间作为起始时间的。——固定频率执行。
(4)创建单个执行定时任务的线程池——Executors.newSingleThreadScheduledExecutor();
单个线程的线程池有什么意义?无需频繁的创建和销毁线程;可以将任务放到任务队列中,从而可以更好的分配、管理以及存储任务;
(5)创建单个线程的线程池——Executors.newSingleThreadExecutor();
(6)JDK8+ 根据当前工作环境(CPU核心数、任务量)创建异步线程池;——Executors.newWorkStealingPool();——最多可创建等于CPU核数的线程数;
- 同步:按照某种规则按序执行;
- 异步: 执行即结束;效率快;
- 同步执行的流程:main调用线程池——线程池执行结束之后——关闭线程池,main也会随之关闭;
- 异步执行的流程:main调用异步线程池——异步线程池后台执行,对于main线程来说,异步线程池已经执行完成,关闭main线程;
(7)使用ThreadPoolExecutor方式
5.线程池的执行流程
当拿到一个任务之后,会判断当前线程池里面的线程数量是否达到了最大值,如果没有达到创建新的线程执行任务;当任务来了之后,线程池的线程数量已经是最大值,并且没有空闲线程,当前的任务会被放到线程池的任务队列里面等待执行。
6.线程池包含:
(1)线程
(2)任务队列
7.Executors创建线程的问题
(1)线程数量不可控;——线程的过度切换和争抢——执行执行比较慢;
(2)任务数量不可控(任务数为Integer.MAX_VALUE),当任务量比较大的时候,会造成OOM异常;
8. 拒绝策略
自定义拒绝策略
(1)newRejectedExecutionHandler();
JDK 4种策略——默认的拒绝策略
(2)ThreadPoolExecutor.AbortPolicy();
(3)ThreadPoolExecutor.CallerRunsPolicy();
(4)忽略最新加入任务队列的任务——ThreadPoolExecutor.DiscardOldestPolicy();
(5)忽略(新)任务——ThreadPoolExecutor.DiscardPolicy();
9.线程池的2种执行方式:
(1)execute 执行(new Runnable)——无返回值;
(2)submit执行 (new Runnable)——无返回值;
submit执行 ( new callable)——有返回值;
execute只能执行Runnable任务,它是无返回值的;submit既能执行Runnable无返回值的任务,也能执行Callable有返回值的任务;
execute执行任务如果有OOM异常,会将异常打印到控制台;submit执行任务出现了OOM异常时不会打印异常;
10.线程池的特征
线程池相比于线程来说是长生命周期,即使没有任务了,也会运行并等待任务;
- 11.线程池的关闭
shutdown();——拒绝新任务加入,等待线程池中的任务队列执行完之后,再停止线程池;
shutdownNow();——拒绝执行新任务,不会等待任务队列中的任务执行完成,就停止线程池;
12.线程池状态
线程池状态(5种)不等于线程的状态(6种);
- RUNNING——线程池创建之后的初始状态,此状态可以执行任务;
- SHUTDOWN——该状态线程池不在接收新任务,但是会将工作队列中的任务执行完成;
- STOP——调用shutdownNow()进入STOP状态;
- TIDYING——当pool为空时,进入TIDYING状态;
- TERMINATED——销毁状态;