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

查看:19
本文介绍了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.

如果 shutdown 没有被调用,调用 ExecutorService.awaitTermination() 似乎什么都不做.

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.

将其实现为从任务中显式调用的单独原语,可以将此逻辑与线程池实现分离,并允许您将多个独立的递归任务树提交到同一个池中.

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() 应该在 finally 块中调用,以使其免受可能的异常的影响.

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天全站免登陆