单线程、Callable、CompletableFuture性能比较,推荐使用CompletableFuture

在多线程合并返回结果时可以用到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;
    }

版权声明:本文为qq_22744093原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。