单线程、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 add1= () -> {
            long callableNum =0;
            for (long i = 0; i < 200000000; i++) {
                callableNum++;
            }
            return callableNum;
        };
        Callable add2= () -> {
            long callableNum =0;
            for (long i = 0; i < 200000000; i++) {
                callableNum++;
            }
            return callableNum;
        };
        FutureTask integerFutureTask = new FutureTask<>(add1);
        new Thread(integerFutureTask).start();
        FutureTask 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 longCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
            long callableNum = 0;
            for (long i = 0; i < 200000000; i++) {
                callableNum++;
            }
            return callableNum;
        });
        CompletableFuture 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  CompletableFuture supplyAsync(Supplier supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }
    
static  CompletableFuture asyncSupplyStage(Executor e,
                                                     Supplier f) {
        if (f == null) throw new NullPointerException();
        CompletableFuture d = new CompletableFuture();
        e.execute(new AsyncSupply(d, f));
        return d;
    }

你可能感兴趣的:(java,java)