线程池
更细节的:https://blog.csdn.net/weixin_40271838/article/details/79998327
1. 为什么要使用线程池?
假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。 如果:T1 + T3 远大于 T2,这个时候就可以使用线程池了。官方一点的讲法:创建线程和销毁线程的花销是比较大的,这些时间有可能比处理业务的时间还要长。这样频繁的创建线程和销毁线程,再加上业务工作线程,消耗系统资源的时间,可能导致系统资源不足,这个时候就需要使用线程池了。
2. 线程池的作用:
1.提高效率 创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。
2.方便管理 可以编写线程池管理代码对池中的线程同一进行管理。
3. 常见的线程池
1.newSingleThreadExecutor
创建一个固定数量的线程池,可控制线程最大并发数,提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行。
volatile int runState;
static final int RUNNING = 0;
static final int SHUTDOWN = 1;
static final int STOP = 2;
static final int TERMINATED = 3;
runState表示当前线程池的状态,它是一个volatile变量用来保证线程之间的可见性;至于为什么用volatile 可以看https://www.cnblogs.com/jkzr/p/10576268.html
RUNNING 状态:线程池正在运行;SHUTDOWN状态:此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
STOP状态:此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;TERMINATED状态:所有工作线程已经销毁,任务缓存队列已经清空或执行结束后。
6. 任务提交给线程池之后的处理策略,这里总结一下主要有4点:
1.如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
2.如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
3.如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
4.如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。