java ExecutorService不会并行运行任务

mzsu5hc0  于 2023-02-15  发布在  Java
关注(0)|答案(3)|浏览(153)

我有一个递归批量任务,我将它放入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();
    }
}

请告诉我,我做错了什么?提前非常感谢任何能给我指出正确方向的人。

tgabmvqs

tgabmvqs1#

您的代码示例包含ExecutorService.invoke和ExecutorService.execute,而您应该调用ExecutorService.submit,这有点奇怪。
ExecutorService documentation还包含了一个用法示例。然后还有一些关于这个主题的不错的Java Tutorial

tjjdgumg

tjjdgumg2#

不要创建任何线程,这是ExecutorService的工作。
你不想execute这个任务,你想submit这个任务,然后你会得到一个Future<T>返回。
由于您已经有了一个集合,可以考虑invokeAll,它返回List<Future<T>>,并节省了遍历列表的时间。

gudnpqoy

gudnpqoy3#

TL;医生

  • execute更改为submit
  • 关闭执行器服务时等待终止。

Executor#execute不一定是异步的

您需要仔细阅读文档,这是一个棘手的领域。
ExecutorService#execute方法继承自超级接口Executor
Executor的Javadoc说明:
但是,Executor接口并不严格要求执行是异步的
因此,您传递给execute的任何Runnable都可能在后台线程上运行,也可能不运行。

ExecutorService#submit始终为异步

如果您确实希望Runnable在后台线程上运行,请传递给ExecutorService#submit
更改此行:

threadList.forEach(executorService::execute);

......到这个:

threadList.forEach(executorService::submit);

关机

您对ExecutorService#shutdown的调用不足。您需要等待提交的任务完成。
请参见Javadoc中为ExecutorService提供的样板方法shutdownAndAwaitTermination
或者,在Java 19+中,调用ExecutorService#close

相关问题