CompletableFuture 详解

本文介绍了CompletableFuture的使用,它继承于Future,可实现多线程的串行、并行和聚合关系。文中阐述了其创建方式,包括使用默认和自定义线程池;构建异步任务的方法,如runAsync、supplyAsync等;还详细讲解了CompletableFuture接口的各类方法及功能。

目录

一. 前言

二. 创建方式

2.1. 用默认线程池

2.2. 用自定义线程池

三. 构建异步任务

3.1. runAsync

3.2. supplyAsync

3.3. anyOf

3.4. allOf

四. CompletableFuture 接口

4.1. 基本方法

4.2. 单任务结果消费

4.2.1. thenApply

4.2.2. thenAccept

4.2.3. thenRun

4.3. 合并消费结果

4.3.1. thenCombine

4.3.2. thenAcceptBoth

4.3.3. runAfterBoth

4.4. 任一结果消费

4.4.1. applyToEither

4.4.2. acceptEither

4.4.3. runAfterEither

4.5. 级联任务

4.5.1. thenCompose

4.6. 单任务结果或异常消费

4.6.1. handle

4.6.2. whenComplete

4.6.3. exceptionally

五. 总结


一. 前言

    CompletableFuture继承于java.util.concurrent.Future,它本身具备Future的所有特性,并且基于JDK1.8的流式编程以及Lambda表达式等实现一元操作符、异步性以及事件驱动编程模型,可以用来实现多线程的串行关系,并行关系,聚合关系。它的灵活性和更强大的功能是Future无法比拟的。

二. 创建方式

2.1. 用默认线程池

CompletableFuture<String> future = new CompletableFuture<>();

默认使用 ForkJoinPool.commonPool(),commonPool是一个会被很多任务 共享 的线程池,比如同一 JVM 上的所有 CompletableFuture、并行 Stream 都将共享 commonPool,commonPool 设计时的目标场景是运行 非阻塞的 CPU 密集型任务,为最大化利用 CPU,其线程数默认为 CPU 数量 -1。

2.2. 用自定义线程池

ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 4, 3,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
                new ThreadPoolExecutor.DiscardOldestPolicy());
CompletableFuture.runAsync(() -> System.out.println("Hello World!"), pool);

三. 构建异步任务

3.1. runAsync

runAsync() 进行数据处理,接收前一步骤传递的数据,无返回值。

// 源码

public static CompletableFuture<Void> runAsync(Runnable runnable) {
    return asyncRunStage(asyncPool, runnable);
}

public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                   Executor executor) {
    return asyncRunStage(screenExecutor(executor), runnable);
}
// 示例
public static void runAsync() {
    // 使用默认线程池
    CompletableFuture cf = CompletableFuture.runAsync(() -> System.out.println("Hello World!"));
    assertFalse(cf.isDone());    
    // 使用自定义线程池
    CompletableFuture.runAsync(() -> System.out.println("Hello World!"),                                                 
        Executors.newSingleThreadExecutor());
}

3.2. supplyAsync

supplyAsync() 进行数据处理,接收前一步骤传递的数据,处理加工后返回。有返回值,返回数据类型可以和前一步骤返回的数据类型不同。

// 源码

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
    return asyncSupplyStage(asyncPool, supplier);
}

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
    return asyncSupplyStage(screenExecutor(executor), supplier);
}
// 示例
public static void supplyAsync() throws ExecutionException, InterruptedException {
	CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> {
		try {
			//ForkJoinPool.commonPool-worker-1线程
			System.out.println(Thread.currentThread().getName());
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return "hello";
	});
	//阻塞等待3秒 
	String result = f.get();
	//main线程
	System.out.println(Thread.currentThread().getName());
	System.out.println(result);
}

3.3. anyOf

anyOf(CompletableFuture<?>... cfs) 合并多个complete为一个,等待其中之一完成。当任何一个CompletableFuture完成的时候【相同的结果类型】,返回一个新的CompletableFuture。

// 示例
private static void anyOf() throws ExecutionException, InterruptedException {
	CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			throw new IllegalStateException(e);
		}
		return "Result of Future 1";
	});

	CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			throw new IllegalStateException(e);
		}
		return "Result of Future 2";
	});

	CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			throw new IllegalStateException(e);
		}
		return "Result of Future 3";
	});
	CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2, future3);
	System.out.println(anyOfFuture.get()); // Result of Future 2
}

3.4. allOf

allOf(CompletableFuture<?>... cfs) 合并多个complete为一个,等待全部完成。当CompletableFuture全部完成的时候【相同的结果类型】,返回一个新的CompletableFuture。

// 示例

// 创建异步执行任务:
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread()+" start job1,time->"+System.currentTimeMillis());
	try {
		Thread.sleep(2000);
	} catch (InterruptedException e) {
	}
	System.out.println(Thread.currentThread()+" exit job1,time->"+System.currentTimeMillis());
	return 1.2;
});
CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread()+" start job2,time->"+System.currentTimeMillis());
	try {
		Thread.sleep(1500);
	} catch (InterruptedException e) {
	}
	System.out.println(Thread.currentThread()+" exit job2,time->"+System.currentTimeMillis());
	return 3.2;
});
CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(()->{
	System.out.println(Thread.currentThread()+" start job3,time->"+System.currentTimeMillis());
	try {
		Thread.sleep(1300);
	} catch (InterruptedException e) {
	}
//            throw new RuntimeException("test");
	System.out.println(Thread.currentThread()+" exit job3,time->"+System.currentTimeMillis());
	return 2.2;
});
//allof等待所有任务执行完成才执行cf4,如果有一个任务异常终止,则cf4.get时会抛出异常,都是正常执行,cf4.get返回null
//anyOf是只有一个任务执行完成,无论是正常执行或者执行异常,都会执行cf4,cf4.get的结果就是已执行完成的任务的执行结果
CompletableFuture cf4=CompletableFuture.allOf(cf,cf2,cf3).whenComplete((a,b)->{
	if(b!=null){
		System.out.println("error stack trace->");
		b.printStackTrace();
	}else{
		System.out.println("run succ,result->"+a);
	}
});
System.out.println("main thread start cf4.get(),time->"+System.currentTimeMillis());
//等待子任务执行完成
System.out.println("cf4 run result->"+cf4.get());
System.out.println("main thread exit,time->"+System.currentTimeMillis());

四. CompletableFuture 接口

4.1. 基本方法

isDone():判断任务是否完成。三种完成情况:normally(正常执行完毕)、exceptionally(执行异常)、via cancellation(取消)。

get():阻塞获取结果或抛出受检测异常,需要显示进行try...catch处理。

get(long timeout,TimeUnit unit):超时阻塞获取结果。

getNow(T valueIfAbsent):若当前任务无结果,则返回valueIfAbsent,否则返回已完成任务的结果。

getNumberOfDependents():返回依赖当前任务的任务数量,主要用于监控。

cancel(boolean mayInterruptIfRunning):取消任务,若一个任务未完成,则发生CancellationException异常。其相关未完成的子任务也会以CompletionException结束。

isCancelled():是否已取消,在任务正常执行完成前取消,才为true。否则为false。

join():阻塞获取结果或抛出非受检异常。

complete(T value):设置任务结果,任务正常结束,之后的任务状态为已完成。

completeExceptionally(Throwable ex):设置任务异常结果,任务异常结束,之后的任务状态为已完成。

completeOnTimeout(T value,long timeout,TimeUnit unit):JDK9新增,设置任务完成超时时间,若在指定时间内未正常完成,则以给定的value为任务结果。

isCompletedExceptionally():判断任务是否异常结束。异常可能的原因有:取消、显示设置任务异常结果、任务动作执行异常等。

orTimeout(long timeout,TimeUnit unit):JDK9新增,设置任务完成超时时间,若在指定时间内未正常完成,则任务会以异常(TimeoutException)结束。

4.2. 单任务结果消费

4.2.1. thenApply

thenApply():在前一个阶段上应用thenApply函数,将上一阶段完成的结果作为当前阶段的入参,有返回值。

// 源码

public <U> CompletableFuture<U> thenApply(
	Function<? super T,? extends U> fn) {
	return uniApplyStage(null, fn);
}

public <U> CompletableFuture<U> thenApplyAsync(
	Function<? super T,? extends U> fn) {
	return uniApplyStage(asyncPool, fn);
}

public <U> CompletableFuture<U> thenApplyAsync(
	Function<? super T,? extends U> fn, Executor executor) {
	return uniApplyStage(screenExecutor(executor), fn);
}
// 示例
public static void thenApply() throws ExecutionException, InterruptedException {
    CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
        System.out.println(s);
        return s.toUpperCase();
    }).thenApply(s->{
        System.out.println(s);
        return s + ":body";
    });
    System.out.println(cf.get());
}

then意味着这个阶段的动作发生当前的阶段正常完成之后。本例中,当前节点完成,返回字符串message。
apply意味着返回的阶段将会对结果前一阶段的结果应用一个函数。函数的执行会被阻塞。

4.2.2. thenAccept

thenAccept():消费前一阶段的结果,无返回值。

// 源码

public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
	return uniAcceptStage(null, action);
}

public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
	return uniAcceptStage(asyncPool, action);
}

public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
											   Executor executor) {
	return uniAcceptStage(screenExecutor(executor), action);
}
// 示例

public static void thenAccept() throws InterruptedException {
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
        return "message";
    }).thenAccept((consumer) -> {
        System.out.println(consumer);
    });
}

4.2.3. thenRun

thenRun():当上一阶段完成后,执行本阶段的任务,无返回值,并且无入参。

// 源码

public CompletableFuture<Void> thenRun(Runnable action) {
	return uniRunStage(null, action);
}

public CompletableFuture<Void> thenRunAsync(Runnable action) {
	return uniRunStage(asyncPool, action);
}

public CompletableFuture<Void> thenRunAsync(Runnable action,
											Executor executor) {
	return uniRunStage(screenExecutor(executor), action);
}
// 示例

public static void thenRun() throws InterruptedException {
    CompletableFuture.supplyAsync(() -> {
        //执行异步任务
        System.out.println("执行任务");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }).thenRun(() -> {
        // Computation Finished.
        System.out.println("上一阶段任务执行完成");
    });
    Thread.sleep(2000);
}

4.3. 合并消费结果

4.3.1. thenCombine

thenCombine():合并另外一个任务,两个任务都完成后,执行BiFunction,入参为两个任务结果,返回新结果。

如果CompletableFuture依赖两个前面阶段的结果, 它复合两个阶段的结果再返回一个结果,我们就可以使用thenCombine()函数。整个流水线是同步的。

// 源码

public <U,V> CompletableFuture<V> thenCombine(
	CompletionStage<? extends U> other,
	BiFunction<? super T,? super U,? extends V> fn) {
	return biApplyStage(null, other, fn);
}

public <U,V> CompletableFuture<V> thenCombineAsync(
	CompletionStage<? extends U> other,
	BiFunction<? super T,? super U,? extends V> fn) {
	return biApplyStage(asyncPool, other, fn);
}

public <U,V> CompletableFuture<V> thenCombineAsync(
	CompletionStage<? extends U> other,
	BiFunction<? super T,? super U,? extends V> fn, Executor executor) {
	return biApplyStage(screenExecutor(executor), other, fn);
}
// 示例

public static void thenCombine() {
    CompletableFuture<String> cfA = CompletableFuture.supplyAsync(() -> {
        System.out.println("processing a...");
        return "hello";
    });
    CompletableFuture<String> cfB = CompletableFuture.supplyAsync(() -> {
        System.out.println("processing b...");
        return " world";
    });
    CompletableFuture<String> cfC = CompletableFuture.supplyAsync(() -> {
        System.out.println("processing c...");
        return ", I'm CodingTao!";
    });
    cfA.thenCombine(cfB, (resultA, resultB) -> {
        System.out.println(resultA + resultB);  // hello world
        return resultA + resultB;
    }).thenCombine(cfC, (resultAB, resultC) -> {
        System.out.println(resultAB + resultC); // hello world, I'm CodingTao!
        return resultAB + resultC;
    });
}

4.3.2. thenAcceptBoth

thenAcceptBoth():合并另外一个任务,两个任务都完成后,执行这个方法等待第一个阶段的完成,它的结果传给一个指定的返回CompletableFuture函数,它的结果就是返回的CompletableFuture的结果,入参为两个任务结果,不返回新结果。

public <U> CompletableFuture<Void> thenAcceptBoth(
	CompletionStage<? extends U> other,
	BiConsumer<? super T, ? super U> action) {
	return biAcceptStage(null, other, action);
}

public <U> CompletableFuture<Void> thenAcceptBothAsync(
	CompletionStage<? extends U> other,
	BiConsumer<? super T, ? super U> action) {
	return biAcceptStage(asyncPool, other, action);
}

public <U> CompletableFuture<Void> thenAcceptBothAsync(
	CompletionStage<? extends U> other,
	BiConsumer<? super T, ? super U> action, Executor executor) {
	return biAcceptStage(screenExecutor(executor), other, action);
}

 

// 示例

private static void thenAcceptBoth() {
    CompletableFuture<String> cfA = CompletableFuture.supplyAsync(() -> "resultA");
    CompletableFuture<String> cfB = CompletableFuture.supplyAsync(() -> "resultB");
    cfA.thenAcceptBoth(cfB, (resultA, resultB) -> {
        //resultA,resultB
        System.out.println(resultA+","+resultB);
    });
}

4.3.3. runAfterBoth

runAfterBoth():合并另外一个任务,两个任务都完成后,执行Runnable,无返回值,无入参,注意,这里的两个任务是同时执行。

// 源码

public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
                                                Runnable action) {
	return biRunStage(null, other, action);
}

public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
												 Runnable action) {
	return biRunStage(asyncPool, other, action);
}

public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
												 Runnable action,
												 Executor executor) {
	return biRunStage(screenExecutor(executor), other, action);
}
// 示例

private static void runAfterBoth() {
    CompletableFuture<String> cfA = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("process a");
        return "resultA";
    });
    CompletableFuture<String> cfB = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("process b");
        return "resultB";
    });
    cfB.runAfterBoth(cfA, () -> {
        //resultA,resultB
        System.out.println("任务A和任务B同时完成");
    });
    try {
        Thread.sleep(6000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

4.4. 任一结果消费

4.4.1. applyToEither

applyToEither():其中任一任务完成后,执行Function,结果转换,入参为已完成的任务结果。返回新结果,要求两个任务结果为同一类型。

// 源码

public <U> CompletableFuture<U> applyToEither(
	CompletionStage<? extends T> other, Function<? super T, U> fn) {
	return orApplyStage(null, other, fn);
}

public <U> CompletableFuture<U> applyToEitherAsync(
	CompletionStage<? extends T> other, Function<? super T, U> fn) {
	return orApplyStage(asyncPool, other, fn);
}

public <U> CompletableFuture<U> applyToEitherAsync(
	CompletionStage<? extends T> other, Function<? super T, U> fn,
	Executor executor) {
	return orApplyStage(screenExecutor(executor), other, fn);
}
// 示例

private static void applyToEither() throws ExecutionException, InterruptedException {
    CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "通过方式A获取商品a";
    });
    CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "通过方式B获取商品a";
    });
    CompletableFuture<String> futureC = futureA.applyToEither(futureB, product -> "结果:" + product);
    //结果:通过方式A获取商品a
    System.out.println(futureC.get());
}

4.4.2. acceptEither

acceptEither():其中任一任务完成后,执行Consumer,消费结果,入参为已完成的任务结果。不返回新结果,要求两个任务结果为同一类型。

// 源码

public CompletableFuture<Void> acceptEither(
	CompletionStage<? extends T> other, Consumer<? super T> action) {
	return orAcceptStage(null, other, action);
}

public CompletableFuture<Void> acceptEitherAsync(
	CompletionStage<? extends T> other, Consumer<? super T> action) {
	return orAcceptStage(asyncPool, other, action);
}

public CompletableFuture<Void> acceptEitherAsync(
	CompletionStage<? extends T> other, Consumer<? super T> action,
	Executor executor) {
	return orAcceptStage(screenExecutor(executor), other, action);
}

4.4.3. runAfterEither

runAfterEither():其中任一任务完成后,执行Runnable,消费结果,无入参,不返回新结果,不要求两个任务结果为同一类型。

场景:假设查询商品a,有两种方式,A和B,但是A和B的执行速度不一样,希望哪个先返回就用那个的返回值。

public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
                                                  Runnable action) {
	return orRunStage(null, other, action);
}

public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
												   Runnable action) {
	return orRunStage(asyncPool, other, action);
}

public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
												   Runnable action,
												   Executor executor) {
	return orRunStage(screenExecutor(executor), other, action);
}

4.5. 级联任务

4.5.1. thenCompose

thenCompose():当原任务完成后,以其结果为参数,返回一个新的任务(而不是新结果,类似flatMap)。

这个方法等待第一个阶段的完成,它的结果传给一个指定的返回CompletableFuture函数,它的结果就是返回的CompletableFuture的结果。

// 源码

public <U> CompletableFuture<U> thenCompose(
	Function<? super T, ? extends CompletionStage<U>> fn) {
	return uniComposeStage(null, fn);
}

public <U> CompletableFuture<U> thenComposeAsync(
	Function<? super T, ? extends CompletionStage<U>> fn) {
	return uniComposeStage(asyncPool, fn);
}

public <U> CompletableFuture<U> thenComposeAsync(
	Function<? super T, ? extends CompletionStage<U>> fn,
	Executor executor) {
	return uniComposeStage(screenExecutor(executor), fn);
}
// 示例

private static void thenCompose() {
    String original = "Message";
    CompletableFuture cf = CompletableFuture.completedFuture(original).thenApply(s -> delayedUpperCase(s))
            .thenCompose(upper -> CompletableFuture.completedFuture(original).thenApply(s -> delayedLowerCase(s))
                    .thenApply(s -> upper + s));
    // MESSAGEmessage
    System.out.println(cf.join());
}

4.6. 单任务结果或异常消费

CompletableFuture.supplyAsync(() -> "resultA")
    .thenApply(resultA -> resultA + " resultB")
    .thenApply(resultB -> resultB + " resultC")
    .thenApply(resultC -> resultC + " resultD");

上面的代码中,任务 A、B、C、D 依次执行,如果任务 A 抛出异常(当然上面的代码不会抛出异常),那么后面的任务都得不到执行。如果任务 C 抛出异常,那么任务 D 得不到执行。
那么我们怎么处理异常呢?看下面3节的示例代码,我们在任务 A 中抛出异常,并对其进行处理: 

4.6.1. handle

handle():任务完成后执行BiFunction,结果转换,入参为结果或者异常,返回新结果。

// 源码

public <U> CompletableFuture<U> handle(
	BiFunction<? super T, Throwable, ? extends U> fn) {
	return uniHandleStage(null, fn);
}

public <U> CompletableFuture<U> handleAsync(
	BiFunction<? super T, Throwable, ? extends U> fn) {
	return uniHandleStage(asyncPool, fn);
}

public <U> CompletableFuture<U> handleAsync(
	BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
	return uniHandleStage(screenExecutor(executor), fn);
}
// 示例

private static void handle() {
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "resultA")
            .thenApply(resultA -> resultA + " resultB")
            // 任务 C 抛出异常
            .thenApply(resultB -> {throw new RuntimeException();})
            // 处理任务 C 的返回值或异常
            .handle(new BiFunction<Object, Throwable, Object>() {
                @Override
                public Object apply(Object re, Throwable throwable) {
                    if (throwable != null) {
                        return "errorResultC";
                    }
                    return re;
                }
            })
            .thenApply(resultC -> {
                System.out.println("resultC:" + resultC);
                return resultC + " resultD";
            });
    System.out.println(future.join());
}

4.6.2. whenComplete

whenComplete():任务完成后执行BiConsumer,结果消费,入参为结果或者异常,不返回新结果

// 源码

public CompletableFuture<T> whenComplete(
	BiConsumer<? super T, ? super Throwable> action) {
	return uniWhenCompleteStage(null, action);
}

public CompletableFuture<T> whenCompleteAsync(
	BiConsumer<? super T, ? super Throwable> action) {
	return uniWhenCompleteStage(asyncPool, action);
}

public CompletableFuture<T> whenCompleteAsync(
	BiConsumer<? super T, ? super Throwable> action, Executor executor) {
	return uniWhenCompleteStage(screenExecutor(executor), action);
}
// 示例

private static void whenComplete() throws ExecutionException, InterruptedException {
    // 创建异步执行任务:
    CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
        System.out.println(Thread.currentThread()+"job1 start,time->"+System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        if(true){
            throw new RuntimeException("test");
        }else{
            System.out.println(Thread.currentThread()+"job1 exit,time->"+System.currentTimeMillis());
            return 1.2;
        }
    });
    //cf执行完成后会将执行结果和执行过程中抛出的异常传入回调方法
    // 如果是正常执行,a=1.2,b则传入的异常为null
    //如果异常执行,a=null,b则传入异常信息
    CompletableFuture<Double> cf2=cf.whenComplete((a,b)->{
        System.out.println(Thread.currentThread()+"job2 start,time->"+System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        if(b!=null){
            System.out.println("error stack trace->");
            b.printStackTrace();
        }else{
            System.out.println("run succ,result->"+a);
        }
        System.out.println(Thread.currentThread()+"job2 exit,time->"+System.currentTimeMillis());
    });
    //等待子任务执行完成
    System.out.println("main thread start wait,time->"+System.currentTimeMillis());
    //如果cf是正常执行的,cf2.get的结果就是cf执行的结果
    //如果cf是执行异常,则cf2.get会抛出异常
    System.out.println("run result->"+cf2.get());
    System.out.println("main thread exit,time->"+System.currentTimeMillis());
}

4.6.3. exceptionally

exceptionally():任务异常,则执行Function,异常转换,入参为原任务的异常信息,若原任务无异常,则返回原任务结果,即不执行转换。

// 源码

public CompletableFuture<T> exceptionally(
        Function<Throwable, ? extends T> fn) {
    return uniExceptionallyStage(fn);
}

五. 总结

1. 以Async结尾的方法,都是异步方法,对应的没有Async则是同步方法,一般都是一个异步方法对应一个同步方法。
2. 以Async后缀结尾的方法,都有两个重载的方法,一个是使用内容的forkjoin线程池,一种是使用自定义线程池。
3. 以run开头的方法,其入口参数一定是无参的,并且没有返回值,类似于执行Runnable方法。
4. 以supply开头的方法,入口也是没有参数的,但是有返回值。
5. 以Accept开头或者结尾的方法,入口参数是有参数,但是没有返回值。
6. 以Apply开头或者结尾的方法,入口有参数,有返回值。
7. 带有either后缀的方法,表示谁先完成就消费谁。

记住上面几条,基本上就可以记住大部分的方法,剩下的其他方法,就可以单独记忆了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流华追梦

你的鼓励将是我创作最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值