我一直在尝试Java 8的CompletableFuture。我的理解是,调用CompletableFuture.supplyAsync(Supplier supplier, Executor executor)总是会在由传入的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,可用于处理它们。我更加好奇的是,如何可能在主线程上执行一些任务。