四种线程池、区别
1. newCachedThreadPool() ----- SynchronousQueue
缓存型线程池,先查看池中有没有以前建立的线程,如果有,就复用.如果没有,就建一个新的线程加入池中。能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。缓存型池子通常用于执行一些生存期很短的异步型任务 。
// Executors 类
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
public ThreadPoolExecutor(int corePoolSize,// 线程数
int maximumPoolSize,// 核心线程满了后额外开的线程窗口
long keepAliveTime,// 没有线程执行时存活时间
TimeUnit unit,// 时间单位
BlockingQueue<Runnable> workQueue) { // 线程队列
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
2. newFixedThreadPool() ----- LinkedBlockingQueue
固定性线程池,fixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程 其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。和cacheThreadPool不同:fixedThreadPool池线程数固定,但是0秒IDLE(无IDLE)。这也就意味着创建的线程会一直存在。所以fixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
3. newScheduledThreadPool() ----- DelayedWorkQueue
调度型线程池。这个池子里的线程可以按schedule依次delay执行,或周期执行 。0秒IDLE(无IDLE)。
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
4. newSingleThreadExecutor ----- **LinkedBlockingQueue **
单例线程,任意时间池中只能有一个线程 。用的是和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
为什么使用
1)提升性能。创建和消耗对象费时费CPU资源
2)防止内存过度消耗。控制活动线程的数量,防止并发线程过多。
不同的原因
1、底层的 BlockingQueue 阻塞队列 任务执行前保存任务的队列 不同
5. 使用时遇到的问题
(1)RejectedExecutionException
线程池中要创建的线程数量大于线程池的最大线程数的时候,新的任务就会被拒绝,,抛出RejectedExecutionException
ThreadPoolExecutor使用的三种缓存队列详解