用于不同类型的 ExecutorService 的用例
Executors 返回满足特定需求的不同类型的 ThreadPools。
-
public static ExecutorService newSingleThreadExecutor()
创建一个 Executor,它使用一个在无界队列中运行的工作线程
newFixedThreadPool(1)
和newSingleThreadExecutor()
之间存在差异,正如 java doc 所说的那样:与其他等效的
newFixedThreadPool(1)
不同,保证返回的执行程序不可重新配置以使用其他线程。这意味着
newFixedThreadPool
可以在程序的后期重新配置:((ThreadPoolExecutor) fixedThreadPool).setMaximumPoolSize(10)
这对newSingleThreadExecutor
来说是不可能的用例:
- 你希望按顺序执行提交的任务。
- 你只需要一个线程来处理你的所有请求
缺点:
- 无界队列是有害的
-
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个线程池,该池重用在共享的无界队列中运行的固定数量的线程。在任何时候,最多 nThreads 线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到线程可用
用例:
- 有效使用可用核心。将
nThreads
配置为Runtime.getRuntime().availableProcessors()
- 当你确定线程数不应超过线程池中的数字时
缺点:
- 无界队列是有害的。
- 有效使用可用核心。将
-
public static ExecutorService newCachedThreadPool()
创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程
用例:
- 对于短期异步任务
缺点:
- 无界队列是有害的。
- 如果所有现有线程都忙,则每个新任务都将创建一个新线程。如果任务持续时间较长,将创建更多线程,这将降低系统性能。在这种情况下的替代方案:
newFixedThreadPool
-
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个线程池,可以调度命令在给定的延迟后运行,或者定期执行。
用例:
- 处理延迟的重复事件,这将在未来某个时间间隔发生
缺点:
- 无界队列是有害的。
5.
public static ExecutorService newWorkStealingPool()
使用所有可用处理器作为其目标并行级别创建工作窃取线程池
用例:
- 对于分而治之的问题类型。
- 有效使用空闲线程。空闲线程窃取忙线程中的任务。
缺点:
- 无限制的队列大小是有害的。
你可以在所有这些 ExecutorService 中看到一个常见的缺点:无界队列。这将通过 ThreadPoolExecutor 解决
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)
有了 ThreadPoolExecutor
,你可以
- 动态控制线程池大小
- 设置
BlockingQueue
的容量 - 队列满时定义
RejectionExecutionHander
CustomThreadFactory
在线程创建过程中添加一些额外的功能