当前位置: 首页 > 知识库问答 >
问题:

如何使用ExecutorService递归调度任务

邰德业
2023-03-14
final ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 8; i++) {
    executor.execute(() -> { // TASK 1
        Thread.sleep(100); // simulate some work

        executor.execute(() -> { // TASK2
            Thread.sleep(500); // simulate some longer work
        });

    });
}

# terminate when all tasks proceeded
executor.shutdown();
executor.awaitTermination(9999999, TimeUnit.DAYS);
    null
    null

共有1个答案

彭修筠
2023-03-14

您的核心问题是某些任务在运行时可能会或不会产生更多的任务。因此,在关闭之前必须至少等待该任务完成。不能使用executor.shutdown(),否则肯定会过早关闭池。

您必须实现某种机制来编排哪些任务必须等待另一个任务完成,并且必须维护在关闭池之前必须完成的所有任务的列表。

下面是你需要做什么的初步演示。根据任务的相互关系要求,您可能需要更复杂的东西。

final ExecutorService executor = Executors.newFixedThreadPool(4);

class Task1 implements Callable<Void> {

    @Override
    public Void call() throws Exception {
        Thread.sleep(100); // simulate some work
        return null;
    }

}

class Task2 implements Callable<Void> {

    final Future<Void> waitFor;

    Task2(Future<Void> waitFor) {
        // This task must wait for a previous task to complete before commencement.
        this.waitFor = waitFor;
    }

    @Override
    public Void call() throws Exception {
        // Wait for the first task to complete.
        waitFor.get();
        Thread.sleep(100); // simulate some work
        return null;
    }

}

public void test() throws InterruptedException {
    // All of these tasks must complete before we close down the pool.
    List<Future<Void>> waitFor = new ArrayList<>();
    for (int i = 0; i < 8; i++) {
        Future<Void> f1 = executor.submit(new Task1());
        // We must wait for f1 to complete.
        waitFor.add(f1);
        // No need to wait for f2.
        executor.submit(new Task2(f1));
    }
    // Wait for all of the primary tasks to complete.
    for (Future<Void> wait : waitFor) {
        try {
            wait.get();
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    // Can now shut down - will wait for all sub-tasks to complete because they are all in the queue now.
    executor.shutdown();
    executor.awaitTermination(9999999, TimeUnit.DAYS);
}
 类似资料:
  • ExecutorService中的所有线程都在忙着等待滞留在executor服务队列中的任务的任务。 示例代码: 除了为每层创建更多的线程池或者有一个大小不固定的线程池之外,还有什么方法可以避免这种情况吗? 一个实际的例子是,将一些调用项提交给ForkJoinPool.commonPool(),然后这些任务在其方法中使用也提交给CommonPoole的对象。

  • 问题内容: 我使用来执行任务。该任务可以递归创建提交给同一任务的其他任务,那些子任务也可以做到这一点。 我现在遇到的问题是,我要等到所有任务都完成(即所有任务都已完成并且它们没有提交新任务)后再继续。 我无法在主线程中调用,因为这会阻止接受新任务。 如果没有被呼叫,呼叫似乎无能为力。 所以我有点卡在这里。看到所有工人都闲着不难,不是吗?我能想到的唯一优雅的解决方案是直接使用a 并偶尔查询一次。真的

  • 我将可调用任务(使用submit())提交给ExecutionService的实现。有时我似乎遇到了死锁,但无法工作在哪里或为什么会发生,所以我想为任务设置一个超时,我不清楚是如何做到的? 我应该吗 在提交任务时,在ExecutionService上使用invokeAny()而不是submit()并设置超时。我使用submit()一次提交许多任务,我是否也可以这样使用invokeAny(),我很谨

  • 我对和的内部调度机制有点困惑。 同时,显示为不同的,因为它使用了工作窃取算法。如果我理解正确,它意味着一个线程可以从另一个线程窃取一些任务。 然而,我并不真正理解和中实现的机制之间的区别。从我的理解来看,两种机制都应该尽可能减少每个线程的空闲时间。 如果在的情况下,每个线程都有自己的队列,我会理解的。然而,情况并非如此,因为队列是由池的不同线程共享的。

  • 问题内容: 为了估计在给定内存量下递归方法可能实现的最大调用深度,在可能发生堆栈溢出错误之前,用于计算所用内存的(近似)公式是什么? 编辑: 许多人以“取决于”来回答,这是合理的,因此让我们通过一个简单但具体的示例来删除一些变量: 很容易看出,在我的Eclipse IDE中运行该命令时爆炸的次数不到1000(对我来说这很低)。是否可以在不执行此调用深度限制的情况下进行估算? 编辑:我不禁想到Ecl

  • 为了估计递归方法在给定内存量下可能达到的最大调用深度,在可能发生堆栈溢出错误之前,计算所用内存的(近似)公式是什么? 许多人回答说“视情况而定”,这是合理的,所以让我们用一个琐碎但具体的例子来删除一些变量: 很容易看出,在我的EclipseIDE中运行它时,的爆炸性增长不到1000(对我来说,这个数字低得出奇)。这个调用深度限制是否可以在不执行的情况下进行估计? 编辑:我忍不住认为Eclipse有