gpt4 book ai didi

java - 如何使用 ExecutorService 递归调度任务

转载 作者:行者123 更新时间:2023-11-29 05:09:21 27 4
gpt4 key购买 nike

我能否以某种方式在 Java 中使用 ExecutorService 来安排递归任务?

示例代码:(注意:省略 Thread.sleep 周围的 try/catch 以增强可读性)

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);

问题似乎是执行顺序:

  1. 创建执行器
  2. 安排任务 1 (8x) 的执行
  3. 关机
  4. 等待终止
  5. 第一次 hibernate 结束,然后安排任务 2 的执行
  6. 失败,因为关闭后没有任务可以执行。

我相信这是一个普遍的问题。但是,我找不到任何合适的解决方案。我寻求的 list :

要求:

  • 能够从已安排的任务中执行任务
  • 以某种方式在最后阻塞,直到所有任务完成
  • 没有主动等待任务执行
  • 固定最大值使用的线程数
  • 可能是无锁和线程安全的

你能帮帮我吗?我不想实现自己的线程池,因为它必须已经实现了很多次(最好是在标准库中)。

谢谢

最佳答案

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

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

这是您需要执行的操作的基本演示。根据任务的相互关系要求,您可能需要更复杂的东西。

本质上,使用 Callable s 和 Future<Void>.get()等待任何必须完成的任务。

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);
}

关于java - 如何使用 ExecutorService 递归调度任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29230552/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com