这两个任务是否同时执行?

时间:2018-11-04 06:59:46

标签: java completable-future concurrent.futures

CompletableFuture<ResponseList> stsTask = CompletableFuture.supplyAsync(() -> this.stsCompute(question);
CompletableFuture<ResponseList> dssmTask = CompletableFuture.supplyAsync(() -> this.dssmCompute(question);

// Is this line unnecessary?
CompletableFuture<Void> twoFutures = CompletableFuture.allOf(stsTask, dssmTask);

try {
     ResponseList stsList = stsTask.get();
     ResponseList dssmList = dssmTask.get();

     // after the two are done, proceed here
     processResult(stsList, dssmList)
} catch(Exception e){
    // do something
}

我有两个问题:

  1. 这两个任务是否同时执行?还是由于get()方法等待它完成而必须在dssmTask之前执行stsTask?变量'twoFutures'未使用。
  2. CompletableFuture.allOf(stsTask, dssmTask)行是不必要还是必要?

3 个答案:

答案 0 :(得分:1)

如果您未在get上调用twoFutures,则该行是多余的。

如果要等待它们都完成后再对结果进行处理,则应按以下方式重构代码:

stsTask.thenAcceptBoth(dssmTask, (stsResult, dssmResult) -> {
    ResponseList stsList = stsResult; // or stsTask.get()
    ResponseList dssmList = dssmResult; // or dssmTask.get()
    // ...     
});

答案 1 :(得分:1)

是的,如果您的公共fork / join池中有足够的线程,它们将同时执行。 allOf方法返回新的CompletableFuture,当所有给定的CompletableFutures完成时,新的future.get()完成。但是您没有任何合并结果的工具,因此这里不需要。

这里要考虑的另一点是调用stsTask.thenCombine(dssmTask, (stsList, dssmList) -> processResult(stsList, dssmList)); 方法以获取结果。此方法调用处于阻塞状态,将使您的调用线程保持阻塞状态。

所以这是一种更好的方法,

low

答案 2 :(得分:-1)

在不确定多线程任务执行路径时使用记录器:

    private static Logger logger = getLogger(S.class);

    public static void main(String[] args) {


        CompletableFuture<List> stsTask = CompletableFuture.supplyAsync(() -> {
            logger.info("running");
            return new ArrayList();
        });
        CompletableFuture<List> dssmTask = CompletableFuture.supplyAsync(() -> {
            logger.info("running");
            return new ArrayList();
        });

        // Is this line unnecessary?
        CompletableFuture<Void> twoFutures = CompletableFuture.allOf(stsTask, dssmTask);

        logger.info("twoFutures is completed? " + twoFutures.isDone());
        logger.info("allof dose not wait task to complete, just to check if all the task is completed, so this is unnecessary");


        try {
            List stsList = stsTask.get();
            logger.info("stsList completed? " + stsTask.isDone());
            List dssmList = dssmTask.get();
            logger.info("dssmList completed? " + dssmTask.isDone());

            logger.info("get() will block until task is done");

            // after the two are done, proceed here
//          processResult(stsList, dssmList)
        } catch (Exception e) {
            // do something
        }







    }

outPut:

15:18:28.791 [main] INFO cn.lihongjie.S - twoFutures is completed? false
15:18:28.791 [ForkJoinPool.commonPool-worker-2] INFO cn.lihongjie.S - running
15:18:28.791 [ForkJoinPool.commonPool-worker-1] INFO cn.lihongjie.S - running
15:18:28.794 [main] INFO cn.lihongjie.S - allof dose not wait task to complete, just to check if all the task is completed, so this is unnecessary
15:18:28.795 [main] INFO cn.lihongjie.S - stsList completed? true
15:18:28.795 [main] INFO cn.lihongjie.S - dssmList completed? true
15:18:28.795 [main] INFO cn.lihongjie.S - get will block until task is done

我使用logback logger,默认情况下它将打印线程名称,此问题很方便。

  1. 任务是同时执行的,有两个线程在运行它 15:18:28.791 [ForkJoinPool.commonPool-worker-2] INFO cn.lihongjie.S - running 15:18:28.791 [ForkJoinPool.commonPool-worker-1] INFO cn.lihongjie.S - running

  2. allOf是不必要的,直到所有任务完成后,此调用才会阻塞。您可以通过查看日志来找出答案。