【问题标题】:RejectedExecutionException free threads but full queueRejectedExecutionException 空闲线程但队列已满
【发布时间】:2014-04-10 18:49:32
【问题描述】:

是什么导致了这个 RejectedExecutionException?

[Running, pool size = 40, active threads = 3, queued tasks = 20, completed tasks = 180]

线程池执行器:

new ThreadPoolExecutor(30, 40, 10, TimeUnit.MINUTES,
     new ArrayBlockingQueue<Runnable>(20), threadFactory);

池大小为 40,只有 3 个线程处于活动状态,为什么不使用其余线程?

【问题讨论】:

    标签: java multithreading exception


    【解决方案1】:

    RejectedExecutionException 空闲线程但队列已满

    这可能是一个竞争条件。在某个时候,您已向池中添加了 60 多个任务。 40 个在线程中运行,它将第 21 个任务添加到 ArrayBlockingQueue 并拒绝了它。但是,当您返回打印统计信息时,作业已完成,因此此时只有 3 个正在运行的线程。

    您可以添加一个 RejectedExecutionHandler 处理程序来阻止生产者:

    threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                // this will block the producer until there's room in the queue
                executor.getQueue().put(r);
            } catch (InterruptedException e) {
                throw new RejectedExecutionException(
                    "Unexpected InterruptedException", e);
            }
        }
    });
    

    【讨论】:

    • 谢谢。我会调查的。
    • 我找到了问题所在。当核心线程启动(而不是活动)并且您添加任务时,该任务总是首先添加到队列中。因此,如果您在循环中添加许多任务,则可能会在空闲线程有机会从队列中获取任务之前达到队列容量。所以在我的情况下,我需要扩大队列(到 30 个),以便能够同时处理所有添加的任务。
    【解决方案2】:

    您不能使用活动线程数来调试此类问题。 The documentation 表示该数字只是近似值,当您获得 RejectedExecutionException 时它就会过时。

    【讨论】:

    • 谢谢。这就解释了。
    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 2019-12-25
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多