使用CompletableFuture

多线程相关知识 – CompletableFuture

public class TestCompletableFuture {
    public static void main(String[] args) throws InterruptedException {
        // 交给异步线程执行,
        CompletableFuture<Double> completableFuture = CompletableFuture.supplyAsync(TestCompletableFuture::fetchPrice);

        // 定义CompletableFuture完成时和异常时需要回调的实例,回调!!!
        completableFuture.thenAccept((result) -> {
            System.out.println(result);
        });

        CompletableFuture<Double> exceptionally = completableFuture.exceptionally((e) -> {
            e.printStackTrace();
            return null;
        });

        Thread.sleep(100);

    }

    static Double fetchPrice() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (Math.random() < 1) {
            throw new RuntimeException("failed");
        }

        return 5 + Math.random() * 20;
    }

    // 此时也可以,但是需要静态方法,不然编译通不过
    public static int fetchInt() {
        return 1;
    }

}

CompletableFuture 的优点是:

  • 异步任务结束时,会自动回调某个对象的方法
  • 异步任务出错时,会自动回调某个对象的方法;
  • 主线程设置好回调后,不再关心异步任务的执行。

Supplier

接口规范:不需要是狗,长得像狗就行。 ---- 廖大大

java.util.function.Supplier 接口定义如下:

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

Supplier 接口相当简单,它不包含任何静态或默认方法,只有一个抽象方法 T get()。
为实现 Supplier 接口,需要提供一个不传入参数且返回泛型类型(generic type)的方法。根据 Javadoc 的描述,调用 Supplier 时,不要求每次都返回一个新的或不同的结果。Supplier 的一种简单应用是 Math.random 方法,它不传入参数且返回 double 型数据。如例所示,Math.random 方法可以被赋给 Supplier 引用并随时调用。

// 匿名内部类实现
    DoubleSupplier doubleSupplier = new DoubleSupplier() {
        @Override
        public double getAsDouble() {
            return Math.random();
        }
    };

    // lambda 表达式
    DoubleSupplier doubleSupplier2 = () -> Math.random();
    
    /**
     * 方法应用, 静态方法random() 方法符合get() 方法签名, 不一定是狗,长得像狗就行
     * public static double random() {
     *         return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
     *     }
     */
    DoubleSupplier doubleSupplier3 = Math::random;

java.util.function.Consumer 接口亦是如此

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    // 默认方法
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

使用如下:

// 在 java.util.concurrent.CompletableFuture#thenAccept 方法中作为传参数
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
        return uniAcceptStage(null, action);
    }
    
// 使用时
completableFuture.thenAccept((result) -> { 
            System.out.println(result); 
        });

类似的还有 java.util.function.Function

@FunctionalInterface
public interface Function<T, R> {

    /**
     * 此时放心有两个类型,T 和 R, 传入放心参数T ,返回参数类型R 
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

使用用例:

public CompletableFuture<T> exceptionally(
        Function<Throwable, ? extends T> fn) {
        return uniExceptionallyStage(fn);
    }
    
// lambda 表达式 重写 apply(T t) 方法
completableFuture.exceptionally((e) -> {
            e.printStackTrace();
            return null;
        });
上一篇:static修饰的函数作用与意义


下一篇:static与 extern 的用法