CompletableFuture供应异步有时在主线程

时间:2018-05-18 20:32:13

标签: java multithreading completable-future

我一直在尝试使用Java 8 CompletableFutures。我的理解是,调用CompletableFuture.supplyAsync(供应商供应商,执行程序执行程序)将始终在传入的Executor提供的线程中运行作业,但我注意到,当我传递给供应商时,它有时会在主线程上运行它相当简单"。我的测试代码是:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class SyncTest {

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(5);

        CompletableFuture<?>[] cfs = new CompletableFuture<?>[10];
        AtomicInteger mainCount = new AtomicInteger();
        for (int i = 0; i < cfs.length; i++) {
            int index = i;
            CompletableFuture<Integer> cf = 
CompletableFuture.supplyAsync(() -> {
                return index;
            }, pool).thenApply(j -> {
                if (Thread.currentThread().getName().equals("main")) {    
                    mainCount.incrementAndGet();
                }

                System.out.println(Thread.currentThread().getName() + ": " + index + ": doing a heavy computation");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return j;
            });
            cfs[i] = cf;
        }

        System.out.println(Thread.currentThread().getName() + " doing other stuff");
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        CompletableFuture.allOf(cfs).join();
        pool.shutdown();
        System.out.println("Jobs on main: " + mainCount.get());
    }
}

我得到的输出是:

main: 0: doing a heavy computation
main: 1: doing a heavy computation
pool-1-thread-3: 2: doing a heavy computation
pool-1-thread-4: 3: doing a heavy computation
main: 4: doing a heavy computation
main doing other stuff
pool-1-thread-4: 9: doing a heavy computation
pool-1-thread-5: 8: doing a heavy computation
pool-1-thread-2: 7: doing a heavy computation
pool-1-thread-1: 6: doing a heavy computation
pool-1-thread-3: 5: doing a heavy computation
Jobs on main: 3

我理解这是一个相当简单的例子,并且还有其他方法可以使用CompletableFutures,例如thenSupplyAsync和completedFuture来处理它们,我更好奇的是,它们是如何在主要部分执行某些任务的线程。

1 个答案:

答案 0 :(得分:1)

打印&#34;进行繁重计算的任务&#34;使用thenApply调用,这意味着您没有指定执行此任务的执行程序,系统可以自由使用任何执行程序,包括当前线程。

如果您希望此作业在预定义的执行程序上执行,请改为使用thenApplyAsync,使用或不使用第二个参数 - executor。