首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果ThreadPoolExecutor的submit()方法饱和,该如何使其阻塞?

如果ThreadPoolExecutor的submit()方法饱和,该如何使其阻塞?
EN

Stack Overflow用户
提问于 2010-01-05 01:59:37
回答 17查看 60.7K关注 0票数 109

我想创建一个ThreadPoolExecutor,这样当它达到最大大小并且队列已满时,submit()方法会在尝试添加新任务时阻塞。我是否需要为此实现一个自定义的RejectedExecutionHandler,或者是否有一种现有的方法可以使用标准的Java库来实现此目的?

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2010-01-05 02:20:29

我刚刚找到的一个可能的解决方案是:

代码语言:javascript
运行
复制
public class BoundedExecutor {
    private final Executor exec;
    private final Semaphore semaphore;

    public BoundedExecutor(Executor exec, int bound) {
        this.exec = exec;
        this.semaphore = new Semaphore(bound);
    }

    public void submitTask(final Runnable command)
            throws InterruptedException, RejectedExecutionException {
        semaphore.acquire();
        try {
            exec.execute(new Runnable() {
                public void run() {
                    try {
                        command.run();
                    } finally {
                        semaphore.release();
                    }
                }
            });
        } catch (RejectedExecutionException e) {
            semaphore.release();
            throw e;
        }
    }
}

还有其他的解决方案吗?我更喜欢基于RejectedExecutionHandler的东西,因为它似乎是处理这种情况的标准方法。

票数 48
EN

Stack Overflow用户

发布于 2011-04-14 06:15:09

您可以使用ThreadPoolExecutor和blockingQueue:

代码语言:javascript
运行
复制
public class ImageManager {
    BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(blockQueueSize);
    RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
    private ExecutorService executorService =  new ThreadPoolExecutor(numOfThread, numOfThread, 
        0L, TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler);

    private int downloadThumbnail(String fileListPath){
        executorService.submit(new yourRunnable());
    }
}
票数 32
EN

Stack Overflow用户

发布于 2010-01-05 02:07:23

您应该使用CallerRunsPolicy,它在调用线程中执行被拒绝的任务。这样,在任务完成之前,它不能向executor提交任何新任务,此时将有一些空闲的池线程,否则进程将重复。

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.CallerRunsPolicy.html

从文档中:

拒绝的任务

在方法执行(java.lang.Runnable)中提交的新任务将在Executor关闭时被拒绝,当Executor对最大线程和工作队列容量使用有限的界限时也是如此,并且是饱和的。在这两种情况下,execute方法都会调用其RejectedExecutionHandler的RejectedExecutionHandler.rejectedExecution(java.lang.Runnable,java.util.concurrent.ThreadPoolExecutor方法。提供了四个预定义的处理程序策略:

  1. 在默认ThreadPoolExecutor.AbortPolicy中,处理程序在被拒绝时抛出运行时RejectedExecutionException。
  2. 在ThreadPoolExecutor.CallerRunsPolicy中,调用execute本身的线程运行任务。这提供了一种简单的反馈控制机制,可以减慢提交新任务的速度。
  3. 在ThreadPoolExecutor.DiscardPolicy中,无法执行的任务将被简单地删除。
  4. 在ThreadPoolExecutor.DiscardOldestPolicy中,如果未关闭执行器,则会删除位于工作队列头的任务,然后重试执行(这可能会再次失败,导致重复执行)

此外,在调用ThreadPoolExecutor构造函数时,请确保使用有界队列,如ArrayBlockingQueue。否则,什么都不会被拒绝。

编辑:响应您的评论,将ArrayBlockingQueue的大小设置为等于线程池的最大大小,并使用AbortPolicy。

编辑2:好的,我明白你的意思了。这样如何:重写beforeExecute()方法以检查getActiveCount()是否超过getMaximumPoolSize(),如果超过了,则休眠并重试?

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2001086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档