Java ExecutorService:awaitTermination所有递归创建的任务 [英] Java ExecutorService: awaitTermination of all recursively created tasks

查看:492
本文介绍了Java ExecutorService:awaitTermination所有递归创建的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 ExecutorService 执行任务。这个任务可以递归地创建提交到同一个 ExecutorService 的其他任务,这些子任务也可以这样做。

I use an ExecutorService to execute a task. This task can recursively create other tasks which are submitted to the same ExecutorService and those child tasks can do that, too.

我现在有问题,我想等待所有的任务完成(即所有任务完成,他们没有提交新的),然后继续。

I now have the problem that I want to wait until all the tasks are done (that is, all tasks are finished and they did not submit new ones) before I continue.

我不能在主线程中调用 ExecutorService.shutdown(),因为这会阻止新任务被 ExecutorService

I cannot call ExecutorService.shutdown() in the main thread because this prevents new tasks from being accepted by the ExecutorService.

并且调用 ExecutorService.awaitTermination()似乎什么都不做,如果 shutdown 尚未被调用。

And Calling ExecutorService.awaitTermination() seems to do nothing if shutdown hasn't been called.

所以我有点卡在这里。对于 ExecutorService 来说,看不到所有工人都是空闲的,是不是很难呢?我可以想出的唯一不值得的解决方案是直接使用 ThreadPoolExecutor 并每次查询其 getPoolSize()一会儿。

So I am kinda stuck here. It can't be that hard for the ExecutorService to see that all workers are idle, can it? The only inelegant solution I could come up with is to directly use a ThreadPoolExecutor and query its getPoolSize() every once in a while. Is there really no better way do do that?

推荐答案

如果递归任务树中的任务数量最初未知,或许最简单的方法是实现自己的同步原语,某种反信号量,并在任务之间共享它。在提交每个任务之前,递增一个值,当任务完成时,它递减该值,并等待值为0。

If number of tasks in the tree of recursive tasks is initially unknown, perhaps the easiest way would be to implement your own synchronization primitive, some kind of "inverse semaphore", and share it among your tasks. Before submitting each task you increment a value, when task is completed, it decrements that value, and you wait until the value is 0.

显式地实现它作为一个单独的原语调用from tasks从线程池实现中解耦这个逻辑,并允许你提交几个独立的递归任务树到同一个池中。

Implementing it as a separate primitive explicitly called from tasks decouples this logic from the thread pool implementation and allows you to submit several independent trees of recursive tasks into the same pool.

这样:

public class InverseSemaphore {
    private int value = 0;
    private Object lock = new Object();

    public void beforeSubmit() {
        synchronized(lock) {
            value++;
        }
    }

    public void taskCompleted() {
        synchronized(lock) {
            value--;
            if (value == 0) lock.notifyAll();
        }
    }

    public void awaitCompletion() throws InterruptedException {
        synchronized(lock) {
            while (value > 0) lock.wait();
        }
    }
}

注意 taskCompleted()应在最后块中调用,以免对可能的异常。

Note that taskCompleted() should be called inside a finally block, to make it immune to possible exceptions.

另请注意,在提交任务之前,提交线程应调用 beforeSubmit(),而不是

Also note that beforeSubmit() should be called by the submitting thread before the task is submitted, not by the task itself, to avoid possible "false completion" when old tasks are completed and new ones not started yet.

编辑:使用时的重要问题模式固定。

Important problem with usage pattern fixed.

这篇关于Java ExecutorService:awaitTermination所有递归创建的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆