Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 等待第一个线程完成,然后并行运行其他线程_Java_Multithreading_Parallel Processing_Java 8 - Fatal编程技术网

Java 等待第一个线程完成,然后并行运行其他线程

Java 等待第一个线程完成,然后并行运行其他线程,java,multithreading,parallel-processing,java-8,Java,Multithreading,Parallel Processing,Java 8,在我的主流程中,我想并行地完成一些任务。假设我有4个任务要在一个单独的流程中执行,但在这4个任务中,第一个任务需要完成,然后才能并行运行其他任务 我认为我的代码符合我的要求,但有更好的方法吗 public static void main(String[] args) { System.out.println("In main"); ExecutorService executor = Executors.newSingleThreadExecutor();

在我的主流程中,我想并行地完成一些任务。假设我有4个任务要在一个单独的流程中执行,但在这4个任务中,第一个任务需要完成,然后才能并行运行其他任务

我认为我的代码符合我的要求,但有更好的方法吗

public static void main(String[] args) {
        System.out.println("In main");

        ExecutorService executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> {
            runParalleltasks();
        });

        executor.shutdown();
        System.out.println("Exiting main");
    }

    private static void runParalleltasks() {
        System.out.println("Running parallel tasks");
        doTask1();
        ExecutorService executor = Executors.newFixedThreadPool(3);
        executor.submit(() -> {
            doTask2();
        });
        executor.submit(() -> {
            doTask3();
                });
        executor.submit(() -> {
            doTask4();
        });

        executor.shutdown();
        System.out.println("Exiting parallel tasks");
    }

你可能想看看新设施。对于像您这样的小案例,它可能不会提供很多帮助,但它提供了很多灵活性:

import static java.util.concurrent.CompletableFuture.allOf;
import static java.util.concurrent.CompletableFuture.runAsync;

runAsync(() -> doTask1(), executor)
        .thenCompose(v -> allOf(
                runAsync(() -> doTask2(), executor),
                runAsync(() -> doTask3(), executor),
                runAsync(() -> doTask4(), executor)
        ));
如果您需要将task1的输出传递给相关任务,那么这种方法将真正发挥作用。假设
doTask1
返回一个
字符串
,而
doTask2
接受一个
字符串
。现在,对于第一个任务,我们应该使用
supplyAsync
,而不是
runAsync

supplyAsync(() -> doTask1(), executor)
        .thenCompose(resultOf1 -> allOf(
                runAsync(() -> doTask2(resultOf1), executor),
                runAsync(() -> doTask3(), executor),
                runAsync(() -> doTask4(), executor)
        ));

您也可以使用
ExecutorService
来实现这一点,就像您最初的方法一样。您只需使用
submit
的结果即可完成后续任务:

ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> task1 = executor.submit(() -> doTask1());
Stream.<Runnable>of(() -> doTask2(), () -> doTask3(), () -> doTask4())
      .forEach(r -> executor.submit(() -> { try {
              task1.get();
              r.run();
          } catch(InterruptedException|ExecutionException ex){}
      }));
executor.shutdown();

为什么有单线程执行器?@matt,因为我想在独立于main的流中执行我的4个任务,但在这4个任务中,第一个任务需要在我可以并行运行其他任务之前完成。我永远不会理解为什么人们需要顺序执行时使用线程。显然,您应该内联运行第一个任务,然后生成其他三个任务。@EJP我需要在与main方法不同的流中执行我的4个任务,4个任务中的最后3个任务取决于第一个任务的输出。有人知道在哪里可以找到这个问题的答案,是可调用的而不是可运行的吗?但是这种方法将我的主要方法保留到完成为止。我需要在不等待这4个任务完成的情况下退出main。在这种情况下,main方法应该返回
CompletableFuture
,而不是
join
ing。我编辑了答案以反映这一点。
for(Runnable r: Arrays.<Runnable>asList(() -> doTask2(), () -> doTask3(), () -> doTask4()))
    executor.submit(() -> { try {
            task1.get();
            r.run();
        } catch(InterruptedException|ExecutionException ex){}
    });