1、runAsync 的基本使用:无返回值,持有一个 Runnable 对象。
System.out.println("begin");
CompletableFuture.runAsync(() -> {
try {
System.out.println("before sleep");
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after sleep");
});
System.out.println("end");
异步任务会执行,但是主线程不回等待异步任务返回结果,也就是不会阻塞当前线程。
输出结果:
begin
end
before sleep
2、supplyAsync 的基本使用:有返回值,持有一个 Supplier 对象。
System.out.println("begin");
CompletableFuture supplyAsync = CompletableFuture.supplyAsync(() -> {
System.out.println("before sleep");
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after sleep");
return new Person();
});
System.out.println("before supplyAsync");
Person person = supplyAsync.get();
System.out.println("after supplyAsync");
System.out.println("end");
只有在调用 get() 方法时,才会执行异步任务,并且带有阻塞当前线程的效果。
输出结果:
begin
before supplyAsync
before sleep
after sleep
after supplyAsync
end
thenAccept、thenRun 这两个方法一般在调用链的最末端使用,区别在于是否可以获取前一个任务的返回值和自己是否返回值
方法名 | 是否可获得前一个任务的返回值 | 是否有返回值 |
---|---|---|
thenApply | 能获得 | 有 |
thenAccept | 能获得 | 无 |
thenRun | 不可获得 | 无 |
CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "this is before");
CompletableFuture future2 = future1.thenApply(obj -> obj + ",this is after");
System.out.println(future2.get());// this is before,this is after
CompletableFuture future3 = CompletableFuture.supplyAsync(() -> "this is before");
future3.thenAccept(System.out::println);// this is before
CompletableFuture future4 = CompletableFuture.supplyAsync(() -> "this is before");
future4.thenRun(() -> {System.out.println("this is after");});// this is after
输出结果:
this is before,this is after
this is before
this is after
thenApply、thenAccept、thenRun 这三个方法都带有一个后缀为 Async 的方法
CompletableFuture supplyAsync = CompletableFuture.supplyAsync(() -> {
try {
//TimeUnit.MILLISECONDS.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
return "supplyAsync thread is " + Thread.currentThread().getName();
});
CompletableFuture thenApply = supplyAsync.thenApply(obj -> obj + ",thenAccept thread is " + Thread.currentThread().getName());
CompletableFuture thenApplyAsync = thenApply.thenApplyAsync(obj -> obj + ",thenApplyAsync thread is " + Thread.currentThread().getName());
System.out.println(thenApplyAsync.get());
1、thenCompose():当第一个任务完成时才会执行第二个操作。
CompletableFuture thenCompose = CompletableFuture.supplyAsync(() -> "this is first")
.thenCompose(obj -> CompletableFuture.supplyAsync(() -> obj + ",this is second"));
System.out.println(thenCompose.get());
thenApply 也可以实现相似的功能,但是要 get() 两次。
CompletableFuture> thenApply = CompletableFuture.supplyAsync(() -> "this is first")
.thenApply(obj -> CompletableFuture.supplyAsync(() -> obj + ",this is second"));
System.out.println(thenApply.get().get());
输出结果:
this is first,this is second
2、thenCombine():两个异步任务全部完成时才会执行某些操作。
CompletableFuture first = CompletableFuture.supplyAsync(() -> "this is first");
CompletableFuture second = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "this is second";
});
CompletableFuture thenCombine = first.thenCombine(second, (s1, s2) -> s1 + "," + s2);
System.out.println(thenCombine.get());
输出结果:
this is first,this is second
CompletableFuture first = CompletableFuture.supplyAsync(() -> {
System.out.println("first start");
try {
TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("first return");
return "this is first";
});
CompletableFuture second = CompletableFuture.supplyAsync(() -> {
System.out.println("second start");
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("second return");
return "this is second";
});
CompletableFuture allOf = CompletableFuture.allOf(first, second);
allOf.join();
System.out.println("all return");
输出结果:
first start
second start
second return
first return
all return
当线程 1 和线程2 都开始执行时,join 会带有阻塞功能,会在两条线程都执行完后才继续向下执行。
1、exceptionally 处理异常,并且可以自定义返回值。
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
int i = 10 / 0;
return i + "";
}).exceptionally(e -> {
System.out.println("出现异常:" + e);
return e.getMessage();
}).thenApply(obj -> "result is " + obj);
System.out.println(future.get());
输出结果:
出现异常:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
result is java.lang.ArithmeticException: / by zero
2、handle 同样是处理异常,并且可以自定义返回值。与 exceptionally 区别就是,handle 无论发没发生异常都会执行。另外就是 exceptionally 的自定义返回值类型必须与被处理的线程返回值一致,handle 不需要一致。
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
int i = 10 / 0;
return i;
}).handle((result, e) -> {
if (result == null) {
System.out.println("出现异常:" + e);
return e.getMessage();
}
return result;
}).thenApply(obj -> "result is " + obj);
System.out.println(future.get());
输出结果:
出现异常:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
result is java.lang.ArithmeticException: / by zero