繁体   English   中英

等待所有任务(未知数量)完成-ThreadPoolExecutor

[英]Wait for all tasks (unknown number) to finish - ThreadPoolExecutor

我遇到了这个并发问题,这已经困扰了我好几天了。

基本上,我希望我的ThreadPoolExecutor在关闭之前等待所有任务(未知任务数)完成。

public class AutoShutdownThreadPoolExecutor extends ThreadPoolExecutor{
    private static final Logger logger = Logger.getLogger(AutoShutdownThreadPoolExecutor.class);
    private int executing = 0;
    private ReentrantLock lock = new ReentrantLock();
    private final Condition newTaskCondition = lock.newCondition(); 
    private final int WAIT_FOR_NEW_TASK = 120000;

    public AutoShutdownThreadPoolExecutor(int coorPoolSize, int maxPoolSize, long keepAliveTime,
        TimeUnit seconds, BlockingQueue<Runnable> queue) {
        super(coorPoolSize, maxPoolSize, keepAliveTime, seconds, queue);
    }


    @Override
    public void execute(Runnable command) {
        lock.lock();
        executing++;
        lock.unlock();
        super.execute(command);
    }


    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        try{
            lock.lock();
            int count = executing--;
            if(count == 0) {
                newTaskCondition.await(WAIT_FOR_NEW_TASK, TimeUnit.MILLISECONDS); 
                if(count == 0){
                    this.shutdown();
                    logger.info("Shutting down Executor...");
                }
            }
        }
        catch (InterruptedException e) {
            logger.error("Sleeping task interrupted", e);
        }
        finally{
            lock.unlock();
        }
    }
}

目的是使任务检查任务计数器(正在执行),如果它等于0,它将阻塞一段时间,然后释放其锁,以便其他任务可能有机会执行,而不是过早关闭执行程序。

但是,这没有发生。 执行程序中的所有4个线程都进入等待状态:

"pool-1-thread-4" prio=6 tid=0x034a1000 nid=0x2d0 waiting on condition [0x039cf000]
"pool-1-thread-3" prio=6 tid=0x034d0400 nid=0x1328 waiting on condition [0x0397f000]
"pool-1-thread-2" prio=6 tid=0x03493400 nid=0x15ec waiting on condition [0x0392f000]
"pool-1-thread-1" prio=6 tid=0x034c3800 nid=0x1fe4 waiting on condition [0x038df000]

如果我在Runnable类中放置一条log语句(应该减慢线程速度),问题似乎就消失了。

public void run() {
    //  logger.info("Starting task" + taskName);
        try {
            //doTask();
        }
        catch (Exception e){
            logger.error("task " + taskName + " failed", e);
        }
}

问题类似于此Java ExecutorService帖子:所有递归创建的任务的awaitTermination

我已经采用了原始的发贴人解决方案,并试图在afterExecute()中解决比赛条件,但是它不起作用。

请帮助阐明这一点。 谢谢。

您的任务正在等待这个newTaskCondition ,但是没有任何信号表明这种情况。 因此,所有线程都堆积起来,都在等待newTaskCondition ,直到超时。 另外,阻塞afterExecute将延迟任务的完成,因此这可能不是您想要的。

如果您想让它稍等片刻,看看是否有更多工作要做,则此功能已经存在。 只需调用setKeepAliveTime来设置等待时间,然后设置allowCoreThreadTimeOut以确保可以终止所有线程(包括核心线程)。

我发现了一个非常简单的解决方案。

尽管任务数量事先未知,目的是使主线程等待threadPool中的所有任务完成,但是所有任务的提交时间是已知的(在find-and-submit -task方法之后扫描所有文件)。

我可以简单地调用ThreadPoolExecutor.shutdown()和awaitTermination(Long.MAX_VALUE),以便主线程无限期地等待ThreadPool完成其任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM