我有一个递归批量任务,我将它放入ForkJoinPool线程池中执行。
public class SomeTask extends RecursiveAction {
@Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
startForkJoinPool();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
现在我需要在另外两个并行线程中执行此逻辑。
我决定尝试使用ExecutorService线程池,当我将实体放入其中执行时,我发现它们不是并行执行的,而是其中一个线程在第一个线程的持续时间内处于停顿状态。
public class SomeTask extends RecursiveAction {
@Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
List<Thread> threadList = new ArrayList<>();
threadList.add(new Thread(() -> startForkJoinPool()));
threadList.add(new Thread(() -> startForkJoinPool()));
ExecutorService executorService = Executors.newFixedThreadPool(2);
threadList.forEach(executorService::execute);
executorService.shutdown();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
请告诉我,我做错了什么?提前非常感谢任何能给我指出正确方向的人。
3条答案
按热度按时间tgabmvqs1#
您的代码示例包含ExecutorService.invoke和ExecutorService.execute,而您应该调用ExecutorService.submit,这有点奇怪。
ExecutorService documentation还包含了一个用法示例。然后还有一些关于这个主题的不错的Java Tutorial。
tjjdgumg2#
不要创建任何线程,这是ExecutorService的工作。
你不想
execute
这个任务,你想submit
这个任务,然后你会得到一个Future<T>
返回。由于您已经有了一个集合,可以考虑
invokeAll
,它返回List<Future<T>>
,并节省了遍历列表的时间。gudnpqoy3#
TL;医生
execute
更改为submit
。Executor#execute
不一定是异步的您需要仔细阅读文档,这是一个棘手的领域。
ExecutorService#execute
方法继承自超级接口Executor
。Executor
的Javadoc说明:但是,
Executor
接口并不严格要求执行是异步的因此,您传递给
execute
的任何Runnable
都可能在后台线程上运行,也可能不运行。ExecutorService#submit
始终为异步如果您确实希望
Runnable
在后台线程上运行,请传递给ExecutorService#submit
。更改此行:
......到这个:
关机
您对
ExecutorService#shutdown
的调用不足。您需要等待提交的任务完成。请参见Javadoc中为
ExecutorService
提供的样板方法shutdownAndAwaitTermination
。或者,在Java 19+中,调用
ExecutorService#close
。