用于不同类型的 ExecutorService 的用例

Executors 返回满足特定需求的不同类型的 ThreadPools。

  1. public static ExecutorService newSingleThreadExecutor()

    创建一个 Executor,它使用一个在无界队列中运行的工作线程

    newFixedThreadPool(1)newSingleThreadExecutor() 之间存在差异,正如 java doc 所说的那样:

    与其他等效的 newFixedThreadPool(1) 不同,保证返回的执行程序不可重新配置以使用其他线程。

    这意味着 newFixedThreadPool 可以在程序的后期重新配置:((ThreadPoolExecutor) fixedThreadPool).setMaximumPoolSize(10) 这对 newSingleThreadExecutor 来说是不可能的

    用例:

    1. 你希望按顺序执行提交的任务。
    2. 你只需要一个线程来处理你的所有请求

    缺点:

    1. 无界队列是有害的
  2. public static ExecutorService newFixedThreadPool(int nThreads)

    创建一个线程池,该池重用在共享的无界队列中运行的固定数量的线程。在任何时候,最多 nThreads 线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到线程可用

    用例:

    1. 有效使用可用核心。将 nThreads 配置为 Runtime.getRuntime().availableProcessors()
    2. 当你确定线程数不应超过线程池中的数字时

    缺点:

    1. 无界队列是有害的。
  3. public static ExecutorService newCachedThreadPool()

    创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程

    用例:

    1. 对于短期异步任务

    缺点:

    1. 无界队列是有害的。
    2. 如果所有现有线程都忙,则每个新任务都将创建一个新线程。如果任务持续时间较长,将创建更多线程,这将降低系统性能。在这种情况下的替代方案:newFixedThreadPool
  4. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

    创建一个线程池,可以调度命令在给定的延迟后运行,或者定期执行。

    用例:

    1. 处理延迟的重复事件,这将在未来某个时间间隔发生

    缺点:

    1. 无界队列是有害的。

    5.public static ExecutorService newWorkStealingPool()

    使用所有可用处理器作为其目标并行级别创建工作窃取线程池

    用例:

    1. 对于分而治之的问题类型。
    2. 有效使用空闲线程。空闲线程窃取忙线程中的任务。

    缺点:

    1. 无限制的队列大小是有害的。

你可以在所有这些 ExecutorService 中看到一个常见的缺点:无界队列。这将通过 ThreadPoolExecutor 解决

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)

有了 ThreadPoolExecutor,你可以

  1. 动态控制线程池大小
  2. 设置 BlockingQueue 的容量
  3. 队列满时定义 RejectionExecutionHander
  4. CustomThreadFactory 在线程创建过程中添加一些额外的功能