CachedThreadPool
根据需要创建新线程的线程池。
publicstaticExecutorServicenewCachedThreadPool() { returnnewThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, newSynchronousQueue<Runnable>()); }
如果主线程提交任务的速度高于线程处理任务的速度时, CachedThreadPool 会不断创建新的线程。极 端情况下,这样会导致耗尽 cpu 和内存资源。
使用没有容量的SynchronousQueue作为线程池工作队列,当线程池有空闲线程时, SynchronousQueue.offer(Runnable task) 提交的任务会被空闲线程处理,否则会创建新的线程处理任务。
适用场景:用于并发执行大量短期的小任务。
CachedThreadPool 允许创建的线程数量Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。
ScheduledThreadPoolExecutor
在给定的延迟后运行任务,或者定期执行任务。在实际项目中基本不会被用到,因为有其他方案选择比如 quartz 。
使用的任务队列 DelayQueue 封装了一个 PriorityQueue , PriorityQueue 会对队列中的任务进行 排序,时间早的任务先被执行(即 ScheduledFutureTask 的 time 变量小的先执行),如果time相同则 先提交的任务会被先执行( ScheduledFutureTask 的 squenceNumber 变量小的先执行)。
执行周期任务步骤:
1. 线程从 DelayQueue 中获取已到期的 ScheduledFutureTask(DelayQueue.take()) 。到期任 务是指 ScheduledFutureTask 的 time 大于等于当前系统的时间;
2. 执行这个 ScheduledFutureTask ;
3. 修改 ScheduledFutureTask 的 time 变量为下次将要被执行的时间;
4. 把这个修改 time 之后的 ScheduledFutureTask 放回 DelayQueue 中( DelayQueue.add() )。
适用场景:周期性执行任务的场景,需要限制线程数量的场景。
总结-java中常用的线程池类
1. newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量
2. newSingleThreadExecutor:创建一个使用单个 worker 线程的Executor ,以无界队列方式来运行 该线程。线程池中最多执行一个线程,之后提交的线程将会排在队列中亿次执行
3. newCachedThreadPool:创建一个可进行缓存重复利用的线程池
4. newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行