为了账号安全,请及时绑定邮箱和手机立即绑定

如果ThreadPoolExecutor的commit()方法已经饱和,如何阻止它?

如果ThreadPoolExecutor的commit()方法已经饱和,如何阻止它?

30秒到达战场 2019-08-26 11:20:40
如果ThreadPoolExecutor的commit()方法已经饱和,如何阻止它?我想创建一个ThreadPoolExecutor当它达到其最大大小并且队列已满时,该submit()方法在尝试添加新任务时阻塞。我是否需要为此实现自定义RejectedExecutionHandler,或者是否存在使用标准Java库执行此操作的方法?
查看完整描述

3 回答

?
MM们

TA贡献1886条经验 获得超2个赞

请查看以下四种方法创建NotifyingBlockingThreadPoolExecutor


查看完整回答
反对 回复 2019-08-26
?
一只名叫tom的猫

TA贡献1906条经验 获得超2个赞

我并不总是喜欢CallerRunsPolicy,特别是因为它允许被拒绝的任务“跳过队列”并在之前提交的任务之前执行。此外,在调用线程上执行任务可能比等待第一个插槽变得可用花费更长的时间。

我使用自定义的RejectedExecutionHandler解决了这个问题,它只是暂时阻塞调用线程,然后再次尝试提交任务:

public class BlockWhenQueueFull implements RejectedExecutionHandler {

    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

        // The pool is full. Wait, then try again.
        try {
            long waitMs = 250;
            Thread.sleep(waitMs);
        } catch (InterruptedException interruptedException) {}

        executor.execute(r);
    }}

这个类可以像在任何其他类似的RejectedExecutinHandler中一样在线程池执行器中使用,例如:

executorPool = new ThreadPoolExecutor(1, 1, 10,
                                      TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
                                      new BlockWhenQueueFull());

我看到的唯一缺点是调用线程可能会被锁定比严格必要的时间长(最长250毫秒)。此外,由于这个执行器被有效地递归调用,因此很长时间等待线程可用(小时)可能导致堆栈溢出。

不过,我个人喜欢这种方法。它结构紧凑,易于理解,运行良好。


查看完整回答
反对 回复 2019-08-26
  • 3 回答
  • 0 关注
  • 583 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信