在多线程合并返回结果时可以用到Callble,它和Runnable的作用差不多,Callabe可以返回结果。先面对单线程、callable、FutureTask的增强版CompletableFuture进行性能比较。
public static void main(String[] args) throws ExecutionException, InterruptedException {
//单线程计算累加
Instant start = Instant.now();
long num=0;
for (long i = 0; i < 400000000; i++) {
num++;
}
Instant end = Instant.now();
System.out.println(num+"单线程耗时:"+(end.getNano()-start.getNano()));
Instant startThread = Instant.now();
long num1=0;
//多线程Callable计算累加
Callable<Long> add1= () -> {
long callableNum =0;
for (long i = 0; i < 200000000; i++) {
callableNum++;
}
return callableNum;
};
Callable<Long> add2= () -> {
long callableNum =0;
for (long i = 0; i < 200000000; i++) {
callableNum++;
}
return callableNum;
};
FutureTask<Long> integerFutureTask = new FutureTask<>(add1);
new Thread(integerFutureTask).start();
FutureTask<Long> integerFutureTask2 = new FutureTask<>(add2);
new Thread(integerFutureTask2).start();
Long integer = integerFutureTask.get();
Long integer1 = integerFutureTask2.get();
Instant endThread = Instant.now();
System.out.println(integer+integer1+"多线程耗时:"+(endThread.getNano()-startThread.getNano()));
//jdk8 CompletableFuture 多线程计算累加
Instant startCompletableFuture = Instant.now();
CompletableFuture<Long> longCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
long callableNum = 0;
for (long i = 0; i < 200000000; i++) {
callableNum++;
}
return callableNum;
});
CompletableFuture<Long> longCompletableFuture2 = CompletableFuture.supplyAsync(() -> {
long callableNum = 0;
for (long i = 0; i < 200000000; i++) {
callableNum++;
}
return callableNum;
});
Instant endCompletableFuture = Instant.now();
CompletableFuture.allOf(longCompletableFuture1,longCompletableFuture2).join();
System.out.println(longCompletableFuture1.get()+longCompletableFuture2.get()+"CompletableFuture多线程耗时:"+(endCompletableFuture.getNano()-startCompletableFuture.getNano()));
}
当累加参数I为40000时,结果如下:
40000单线程耗时:1000000
40000多线程耗时:2000000
40000CompletableFuture多线程耗时:3000000
当累加参数I为400000时,结果如下:
400000单线程耗时:3000000
400000多线程耗时:18000000
400000CompletableFuture多线程耗时:9000000
当累加参数I为40000000时,结果如下:
40000000单线程耗时:19000000
40000000多线程耗时:15000000
40000000CompletableFuture多线程耗时:3000000
当累加参数I为400000000时,结果如下:
400000000单线程耗时:155000000
400000000多线程耗时:67000000
400000000CompletableFuture多线程耗时:3000000
结论:当任务不是很耗时,多线程的作用不大,反而性能上比不上单线程。而在多线程中,推荐CompletableFuture去创建任务、开启线程操作,性能比用Callable与FutureTask组合好很多。
分析CompletableFuture比Callable与FutureTask组合好的原因:
查看CompletableFuture.supplyAsync()的源码,看到有个asyncPool->Executor ,用到线程池。
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
static <U> CompletableFuture<U> asyncSupplyStage(Executor e,
Supplier<U> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<U> d = new CompletableFuture<U>();
e.execute(new AsyncSupply<U>(d, f));
return d;
}