使用Java8中的CompletableFuture优化代码的执行效率

使用场景

        一般来说,当我们调用复杂的逻辑运算的方法时,如果采取顺序执行的方式,那么主线程就会被严重堵塞,从而大大影响到代码的执行效率。

        想要解决这个问题,其实也很简单,只要为复杂的任务代码专门创建一个线程去异步执行就行。

详解

CompletableFuture源码中有四个静态方法用来执行异步任务:

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}

public static CompletableFuture<Void> runAsync(Runnable runnable){..}

public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}

        run开头的两个方法,用于执行没有返回值的任务,因为它的入参是Runnable对象,而supply开头的方法显然是执行有返回值的任务了,至于方法的入参,第一个参数是传入执行的方法,主要是迎合了编程式函数的概念,第二个参数是传入一个线程池对象,用于管理线程,如果没有传入自定义的Executor对象将会默认使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码.在实际使用中,一般我们使用自己创建的线程池对象来作为参数传入使用,这样速度会快些。

        大多数时,我们的业务需求都是需要执行有返回值的方法。

使用案例

1、执行异步任务

# 闯入一个匿名函数
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    //....执行任务
    return "hello";}, executor)

2、获取执行结果的几个方法

V get();
V get(long timeout,Timeout unit);
T getNow(T defaultValue);

        上面两个方法是Future中的实现方式,get()会堵塞当前的线程,这就造成了一个问题,如果执行线程迟迟没有返回数据,get()会一直等待下去,因此,第二个get()方法可以设置等待的时间。

   getNow()方法比较有意思,表示当有了返回结果时会返回结果,如果异步线程抛了异常会返回自己设置的默认值。

3、完成案例

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class Test {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 返回的结果我们要声明,例如返回的是String
        CompletableFuture<String> future =  CompletableFuture.supplyAsync( () -> {return "Hello World";});
        // 线程如果没完成,会一直堵塞在这
        System.out.println( future.get());
    }
}

4、结果

猜你喜欢

转载自blog.csdn.net/m0_55868614/article/details/121332621