四种常用线程池介绍与使用场景
1、FixedThreadPool
2、CachedThreadPool
3、SingleThreadExecutor
4、ScheduledThreadPoolExecutor
一、 FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads,
nThreads,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(int nThreads);
1、它是一个固定大小的线程池
2、corePoolSize和maximuPoolSize都对用户指定nThreads
3、keepAliveTime为0,意味着一旦有多余的线程就立即停止掉,这里面keepAliveTime为无效的
4、阻塞队列采用了LinkedBlockingQueue,它是一个无界队列
5、由于阻塞队列是无界队列,因此永远不能可能拒绝任务(因为不可能满)
6、由于采用了无界队列,实际线程数量永远维持在nThreads,maximuPoolSize和keepAliveTime是无效的
二、CachedThreadPool
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,
Integer.MAX_VALUE,
60L,
TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
}
ExecutorService threadPoolExecutor = Executors.newCachedThreadPool();
newCachedThreadPool() 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无回收则新建线程。
1、它是一个无限扩大的线程池
2、它比较适合处理执行时间任务
3、corePoolSize核心线程为0,maximuPoolSize则为为无限大,意味着线程数量可以无限大
4、keepAliveTime为60s,意味着线程空闲60s就要被杀死
5、采用SynchronousQueue装载等待任务,这个阻塞队列没有存储空间,意味着只要收到请求,就必须有一条工作线程处理池,如果但你没有空间的线程那么就会再创建一条新的线程
三、SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor(){
return new ThreadPoolExecutor(1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
ExecutorService threadPoolExecutor = Executors.newSingleThreadExecutor();
1、它只会创建一条工作线程处理任务
2、采用阻塞队列为LinkedBlockingQueue
四、ScheduledThreadPool
ScheduledExecutorService threadPoolExecutor = Executors.newScheduledThreadPool(int corePoolSize);
它接收SchduledFutureTask类型的任务,有两种提交任务的方式:
scheduledAtFixedRate:表示以固定频率执行的任务,如果当前任务耗时较多,超过定时周期period,则当前任务结束后会立即执行。(从上一个任务开始时间计时)
scheduledWithFixedDelay:表示以固定延时执行任务,延时是相对当前任务结束为起点计算开始时间
SchduledFutureTask接收的参数:
time:任务开始的时间
sequenceNumber:任务的序号
period:任务执行的时间间隔
它采用DelayQueue存储等待的任务DelayQueue内部封装了一个PriorityQueue,它会根据time的先后时间排序,若time相同则根据sequenceNumber排序;
DelayQueue也是一个无界队列;
工作线程的执行过程:工作线程会从DelayQueue取已经到期的任务去执行;执行结束后重新设置任务的到期时间,再次放回DelayQueue