ThreadPoolExecutor - 如果池已满,我可以抛出异常吗

ThreadPoolExecutor - Can I throw exception if pool is full

如果无法处理传入的请求,是否可以抛出异常?

所以,我有一些固定的线程池:

private val executor: ThreadPoolExecutor = Executors.newFixedThreadPool(4) as ThreadPoolExecutor

如果无法处理,我不希望请求进入线程队列,我只想抛出异常。

我正在尝试检查 activeCount 并在大于最大池大小时抛出异常,但它没有像我想要的那样工作。

private fun checkPoolSize() {
    if (executor.activeCount >= 4) {
        throw RuntimeException("Request can't be handled. ")
    }
}

您可以使用饱和策略,它会在您的有界队列填满时发挥作用。您可以通过调用 ThreadPoolExecutorsetRejectedExecutionHandler() 来设置饱和策略。开箱即用的实现是 AbortPolicyCallerRunsPolicyDiscardPolicyDiscardOldestPolicyAbortPolicy 是默认值,当有界队列填满时抛出 RejectedExecutionException。您还可以提供自己的自定义实现。

一个解决方案是使用容量为 0 和 java.util.concurrent.ThreadPoolExecutor.AbortPolicy 的队列作为 RejectedExecutionHandler

Executors 中的静态方法不会公开您为此所需的全套参数,因此您需要直接实例化一个 ThreadPoolExecutor。在您的情况下,您可以使用以下内容:

new ThreadPoolExecutor(4,                                     /* Core pool size                    */
                       4,                                     /* Max pool size                     */
                       0, TimeUnit.SECONDS,                   /* Core th. keep-alive               */
                       new MyQueue<Runnable>(0),              /* No queueing allowed               */
                       Executors.defaultThreadFactory(),      /* default                           */
                       new AbortPolicy())                     /* throws when all core threads busy */

几点说明:

  • 0秒(第3、4个参数)对应核心线程保活时间。设置为 0 意味着您的核心线程即使保持空闲也永远不会停止。这是使用 Executors.newFixedThreadPool(4).
  • 时的默认行为
  • Executors.defaultThreadFactory() 是默认线程工厂,与使用 Executors.newFixedThreadPool(4).
  • 时相同
  • 此处核心和最大线程池大小设置为 4(第一个和第二个参数),这对于您的用例来说似乎是合适的。
  • MyQueueBlockingQueue 的一个实现,它接受 0 作为容量(即只能为空。这当然不是队列,但实现它允许与 ThreadPoolExecutor由JDK提供。)。

进一步考虑:

通过对线程池进行如此微调,请注意吞吐量将受到限制。在这里,考虑到提交到线程池的任务有 4 个线程和平均延迟 L 秒,此配置允许的平均吞吐量为 4/L tasks/second.