CompletableFuture异步执行用法详解
常用API
thenAccept()
thenAccept()用法:
1. 此方法【没有返回值】
2. 此方法需要借助【某一个】异步代码逻辑执行
3. 此方法【可以拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenAccept()
5. 此方法不会造成阻塞
private static void thenAcceptTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture
.supplyAsync(() -> "task A");
CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task B";
});
// 放开此睡眠,thenAccept()中逻辑会正常执行
// Thread.sleep(5000);
futureB.thenAccept(b -> {
System.out.println("run task C.");
System.out.println("param:" + b);
});
}
thenRun()
thenRun()用法:
1. 此方法【没有返回值】
2. 此方法需要借助【某一个】异步代码逻辑执行
3. 此方法【不能拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenRun()
5. 此方法不会造成阻塞
private static void thenRunTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture
.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task A";
});
// 放开此睡眠,thenRun()中逻辑会正常执行
// Thread.sleep(5000);
futureA.thenRun(() -> System.out.println("running task B"));
}
thenApply()
thenApply()用法:
1. 此方法【有返回值】
2. 此方法需要借助【某一个】异步代码逻辑执行
3. 此方法【能拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenApply()
5. 此方法会造成阻塞
private static void thenApplyTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture
.supplyAsync(() -> {
a = a + 1;
System.out.println(a + "1");
return "task a ";
});
CompletableFuture<String> futureB = futureA.thenApply(s -> {
// 下面睡眠解注释,会阻塞后续执行
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
a = a + 1;
System.out.println(a + "2");
return s + "and task b ";
});
CompletableFuture<String> future3 = futureB.thenApply(s -> {
a = a + 1;
System.out.println(a + "3");
return s.toUpperCase();
});
System.out.println("4");
System.out.println("a=" + a);
// 输出最后异步任务返回值,会阻塞后续代码块
// System.out.println(future3.join());
}
thenCombine()
thenCombine()用法,用于处理两个阶段的结果:
1. 此方法【有返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【能拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenCombine()
5. 此方法会造成后续代码阻塞
private static void thenCombineTest() {
CompletableFuture<String> taskA = CompletableFuture
.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
CompletableFuture<String> taskC = taskA.thenCombine(taskB, (a, b) -> {
System.out.println("c:" + LocalDateTime.now());
return (a + b).toUpperCase();
});
System.out.println(LocalDateTime.now());
// System.out.println("数据合并:" + taskC.join());
}
thenAcceptBoth()
thenAcceptBoth()用法,用于处理两个阶段的结果:
1. 此方法【无返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【能拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenAcceptBoth()
5. 此方法【不会造成阻塞】
private static void thenAcceptBothTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.thenAcceptBoth(taskB, (a, b) -> {
System.out.println("c:" + LocalDateTime.now());
System.out.println((a + b).toUpperCase());
});
System.out.println(LocalDateTime.now());
}
runAfterBoth()
runAfterBoth()用法,用于处理两个阶段的结果:
1. 此方法【无返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【不能拿到】被依赖的异步逻辑的返回值
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行runAfterBoth()
5. 此方法【不会造成阻塞】
private static void runAfterBothTest() {
CompletableFuture<String> taskA = CompletableFuture
.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.runAfterBoth(taskB, () -> {
System.out.println("c:" + LocalDateTime.now());
});
System.out.println(LocalDateTime.now());
}
applyToEither()
applyToEither()用法,用于处理两个阶段的结果:
1. 此方法【有返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【能返回】被依赖的异步逻辑中【最先拿到的返回值】
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行applyToEither()
5. 此方法【不会造成阻塞】
private static void applyToEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
CompletableFuture<String> taskC = taskA.applyToEither(taskB, info -> {
System.out.println("c:" + LocalDateTime.now());
return info;
});
System.out.println(LocalDateTime.now());
// 此方法阻塞后续代码
// System.out.println("数据输出:" + taskC.join());
}
acceptEither()
acceptEither()用法,用于处理两个阶段的结果:
1. 此方法【没有返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【能返回】被依赖的异步逻辑中【最先拿到的返回值】
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行acceptEither()
5. 此方法【不会造成阻塞】
private static void acceptEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.acceptEither(taskB, info -> {
System.out.println("c:" + LocalDateTime.now());
System.out.println(info);
});
System.out.println(LocalDateTime.now());
}
runAfterEither()
runAfterEither()用法,用于处理两个阶段的结果:
1. 此方法【没有返回值】
2. 此方法需要借助【某两个】异步代码逻辑执行
3. 此方法【不能返回】被依赖的异步逻辑中【最先拿到的返回值】
4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行runAfterEither()
5. 此方法【不会造成阻塞】
private static void runAfterEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.runAfterEither(taskB, () -> {
System.out.println("c:" + LocalDateTime.now());
});
System.out.println(LocalDateTime.now());
}
exceptionally()
exceptionally()用法,用于处理异步逻辑中的异常:
1. 此方法【有返回值】,即使异步逻辑没有返回值,也需要返回null
2. 此方法接收Exception异常对象,并处理异常信息
private static void exceptionallyTest() {
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 0))
.thenApply(s -> " resultA:" + s)
.exceptionally(e -> {
System.out.println(e.getMessage());
return "futureA result: errorA";
});
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "runB:" + 50)
.thenApply(s -> "resultB:" + s)
.exceptionally(e -> "futureB result: errorB");
System.out.println(futureA.join());// 报错进入exceptionally()处理
System.out.println(futureB.join());// 未报错正常结束
}
whenComplete()
whenComplete()用法,用于处理异步逻辑中的异常:
1. 此方法【没有返回值】
2. 此方法不管异步逻辑中是否有异常,都会走这个方法
3. 此方法有两个接收值,一个接收【依赖异步逻辑的返回值】,一个接收【Exception异常】
4. 两种顺序:
4-1. 执行顺序 supplyAsync() -> thenApply() -> whenComplete() -> exceptionally()
4-1-1. whenComplete()和exceptionally()都会接收到异常信息
4-1-2. 最终join()返回的值是exceptionally()的返回值
4-2. 执行顺序 supplyAsync() -> thenApply() -> exceptionally() -> whenComplete()
4-2-1. exceptionally()会接收到异常信息,并处理后返回
4-2-2. whenComplete()接收值是exceptionally()的返回值,接收的异常为null
4-2-3. 最终join()返回的值是exceptionally()的返回值
private static void whenCompleteTest() {
// 顺序一
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 1))
.thenApply(s -> " resultA:" + (100 / 0) )
.whenComplete((s, e) -> {
if (s != null) {
System.out.println("whenComplete:" + s);//未执行
}
if (e == null) {
System.out.println("whenComplete:" + s);//未执行
} else {
//java.lang.ArithmeticException: / by zero
System.out.println("whenComplete:" + e.getMessage());
}
})
.exceptionally(e -> {
//ex:java.lang.ArithmeticException: / by zero
System.out.println("exceptionally():" + e.getMessage());
return "exceptionally() result";
});
// 顺序二
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 1))
.thenApply(s -> " resultA:" + (100 / 0) )
.exceptionally(e -> {
//ex:java.lang.ArithmeticException: / by zero
System.out.println("exceptionally():" + e.getMessage());
return "exceptionally() result";
})
.whenComplete((s, e) -> {
if (e == null) {
//whenComplete:exceptionally() result
System.out.println("whenComplete:" + s);
} else {
//未执行
System.out.println("whenComplete:" + e.getMessage());
}
});
//futureA.join():exceptionally() result
System.out.println("futureA.join():" + futureA.join());
//futureB.join():exceptionally() result
System.out.println("futureB.join():" + futureB.join());
}
handle()
handle()用法,用于处理异步逻辑中的异常:
1. 此方法【有返回值】
2. 此方法不管异步逻辑中是否有异常,都会走这个方法
3. 此方法有两个接收值,一个接收【依赖异步逻辑的返回值】,一个接收【Exception异常】
4. 两种顺序:
4-1. 执行顺序 supplyAsync() -> thenApply() -> handle() -> exceptionally()
4-1-1. handle()会接收到异常信息,并进行处理后返回
4-1-2. 最终join()返回的值是handle()的返回值
4-1-3. 如果handle()也有异常,会进入exceptionally(),并处理异常返回,
最终join()返回的值是exceptionally()的返回值
4-2. 执行顺序 supplyAsync() -> thenApply() -> exceptionally() -> handle()
4-2-1. exceptionally()会接收到异常信息,并处理后返回
4-2-2. handle()接收值是exceptionally()的返回值,接收的异常为null
4-2-3. 最终join()返回的值是handle()的返回值
private static void handleTest() {
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "supplyAsync() result:" + (100 / 0))
.thenApply(s -> "thenApply() result:" + s)
.handle((s, e) -> {
if (e == null) {
System.out.println(s);//未执行
} else {
//java.lang.ArithmeticException: / by zero
System.out.println(e.getMessage());
}
return "handle() result:" + (s == null ? "1000" : s);
})
.exceptionally(e -> {
System.out.println("ex:" + e.getMessage()); //未执行
return "futureA result exceptionally()";
});
System.out.println(futureA.join());//handle() result:1000
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "supplyAsync() result:" + (100 / 0))
.thenApply(s -> "thenApply() result:" + s)
.exceptionally(e -> {
// java.lang.ArithmeticException: / by zero
System.out.println("ex:" + e.getMessage());
return "futureB result exceptionally()";
})
.handle((s, e) -> {
if (e == null) {
System.out.println(s);// futureB result exceptionally()
} else {
System.out.println(e.getMessage());// 未执行
}
return "handle() result:" + (s == null ? "1000" : s);
});
//handle() result:futureB result exceptionally()
System.out.println(futureB.join());
}
CompletableFuture实现简单业务
场景:异步执行逻辑,并每1秒循环获取返回值,直到异步执行结束返回结果
- join()方法和get()方法:会一直阻塞后续的代码执行
- 如果【join()方法和get()】在timer执行之前,会阻塞循环定时器的执行
- 在【join()方法和get()方法】以后的代码都会被阻塞
- get(long timeout, TimeUnit unit)方法:经过指定时间直接返回值,会阻塞后续代码一段时间
但是要注意这个方法调用的位置,可以尝试将此方法放到循环定时器之前调用,会与现在结果大不一样
private static void businessExample() throws ExecutionException,
InterruptedException, TimeoutException {
// 异步执行逻辑
CompletableFuture<String> stringCompletableFuture1 = CompletableFuture
.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 制造异常
int a = 1 / 0;
return "stringCompletableFuture1";
}).exceptionally(e -> {
// 如果逻辑执行有异常,进入此方法处理异常
throw new RuntimeException();
});
// 循环定时获取结果,获取成功后关闭任务
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 如果异步任务执行结束
if (stringCompletableFuture1.isDone()) {
// 关闭并清理任务
timer.cancel();
System.out.println("done = true,stop task total = "
+ timer.purge());
// 输出最终结果
System.out.println("getNow():"
+ LocalDateTime.now() + " "
+ + stringCompletableFuture1.getNow(" END"));
} else {
System.out.println("getNow():"
+ LocalDateTime.now() + " "
+ stringCompletableFuture1.getNow(" RUNNING"));
}
}
}, 0, 1000);
System.out.println("get(time):"
+ stringCompletableFuture1.get(1000L, TimeUnit.MILLISECONDS));
// 代码块
{
System.out.println("join():" + stringCompletableFuture1.join());
System.out.println("get():" + stringCompletableFuture1.get());
}
System.out.println(Thread.currentThread().getName() + "running");
}
整体Demo(以上代码的合并版)
import com.sun.deploy.util.StringUtils;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class TestCompletableFuture {
public static int a = 0;
public static void main(String[] args) throws InterruptedException {
// API实践
// thenAcceptTest();
// thenRunTest();
// thenApplyTest();
// thenCombineTest();
// thenAcceptBothTest();
// runAfterBothTest();
// applyToEitherTest();
// acceptEitherTest();
// runAfterEitherTest();
// exceptionallyTest();
// whenCompleteTest();
// handleTest();
// 业务实例
// businessExample();
}
/**
* handle()用法,用于处理异步逻辑中的异常
* 1. 此方法【有返回值】
* 2. 此方法不管异步逻辑中是否有异常,都会走这个方法
* 3. 此方法有两个接收值,一个接收【依赖异步逻辑的返回值】,一个接收【Exception异常】
* 4. 两种顺序:
* 4-1. 执行顺序 supplyAsync() -> thenApply() -> handle() -> exceptionally()
* 4-1-1. handle()会接收到异常信息,并进行处理后返回
* 4-1-2. 最终join()返回的值是handle()的返回值
* 4-1-3. 如果handle()也有异常,会进入exceptionally(),并处理异常返回,最终join()返回的值是exceptionally()的返回值
* 4-2. 执行顺序 supplyAsync() -> thenApply() -> exceptionally() -> handle()
* 4-2-1. exceptionally()会接收到异常信息,并处理后返回
* 4-2-2. handle()接收值是exceptionally()的返回值,接收的异常为null
* 4-2-3. 最终join()返回的值是handle()的返回值
*/
private static void handleTest() {
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "supplyAsync() result:" + (100 / 0))
.thenApply(s -> "thenApply() result:" + s)
.handle((s, e) -> {
if (e == null) {
System.out.println(s);//未执行
} else {
System.out.println(e.getMessage());//java.lang.ArithmeticException: / by zero
}
return "handle() result:" + (s == null ? "1000" : s);
})
.exceptionally(e -> {
System.out.println("ex:" + e.getMessage()); //未执行
return "futureA result exceptionally()";
});
System.out.println(futureA.join());//handle() result:1000
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "supplyAsync() result:" + (100 / 0))
.thenApply(s -> "thenApply() result:" + s)
.exceptionally(e -> {
System.out.println("ex:" + e.getMessage()); // java.lang.ArithmeticException: / by zero
return "futureB result exceptionally()";
})
.handle((s, e) -> {
if (e == null) {
System.out.println(s);// futureB result exceptionally()
} else {
System.out.println(e.getMessage());// 未执行
}
return "handle() result:" + (s == null ? "1000" : s);
});
System.out.println(futureB.join());//handle() result:futureB result exceptionally()
}
/**
* whenComplete()用法,用于处理异步逻辑中的异常
* 1. 此方法【没有返回值】
* 2. 此方法不管异步逻辑中是否有异常,都会走这个方法
* 3. 此方法有两个接收值,一个接收【依赖异步逻辑的返回值】,一个接收【Exception异常】
* 4. 两种顺序:
* 4-1. 执行顺序 supplyAsync() -> thenApply() -> whenComplete() -> exceptionally()
* 4-1-1. whenComplete()和exceptionally()都会接收到异常信息
* 4-1-2. 最终join()返回的值是exceptionally()的返回值
* 4-2. 执行顺序 supplyAsync() -> thenApply() -> exceptionally() -> whenComplete()
* 4-2-1. exceptionally()会接收到异常信息,并处理后返回
* 4-2-2. whenComplete()接收值是exceptionally()的返回值,接收的异常为null
* 4-2-3. 最终join()返回的值是exceptionally()的返回值
*/
private static void whenCompleteTest() {
// 顺序一
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 1))
.thenApply(s -> " resultA:" + (100 / 0) )
.whenComplete((s, e) -> {
if (s != null) {
System.out.println("whenComplete:" + s);//未执行
}
if (e == null) {
System.out.println("whenComplete:" + s);//未执行
} else {
System.out.println("whenComplete:" + e.getMessage());//java.lang.ArithmeticException: / by zero
}
})
.exceptionally(e -> {
System.out.println("exceptionally():" + e.getMessage()); //ex:java.lang.ArithmeticException: / by zero
return "exceptionally() result";
});
// 顺序二
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 1))
.thenApply(s -> " resultA:" + (100 / 0) )
.exceptionally(e -> {
System.out.println("exceptionally():" + e.getMessage()); //ex:java.lang.ArithmeticException: / by zero
return "exceptionally() result";
})
.whenComplete((s, e) -> {
if (e == null) {
System.out.println("whenComplete:" + s);//whenComplete:exceptionally() result
} else {
System.out.println("whenComplete:" + e.getMessage());//未执行
}
});
System.out.println("futureA.join():" + futureA.join());//futureA.join():exceptionally() result
System.out.println("futureB.join():" + futureB.join());//futureB.join():exceptionally() result
}
/**
* exceptionally()用法,用于处理异步逻辑中的异常
* 1. 此方法【有返回值】,即使异步逻辑没有返回值,也需要返回null
* 2. 此方法接收Exception异常对象,并处理异常信息
*/
private static void exceptionallyTest() {
CompletableFuture<String> futureA = CompletableFuture.
supplyAsync(() -> "runA:" + (100 / 0))
.thenApply(s -> " resultA:" + s)
.exceptionally(e -> {
System.out.println(e.getMessage());
return "futureA result: errorA";
});
CompletableFuture<String> futureB = CompletableFuture.
supplyAsync(() -> "runB:" + 50)
.thenApply(s -> "resultB:" + s)
.exceptionally(e -> "futureB result: errorB");
System.out.println(futureA.join());// 报错进入exceptionally()处理
System.out.println(futureB.join());// 未报错正常结束
}
/**
* runAfterEither()用法,用于处理两个阶段的结果
* 1. 此方法【没有返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【不能返回】被依赖的异步逻辑中【最先拿到的返回值】
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行runAfterEither()
* 5. 此方法【不会造成阻塞】
*/
private static void runAfterEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.runAfterEither(taskB, () -> {
System.out.println("c:" + LocalDateTime.now());
});
System.out.println(LocalDateTime.now());
}
/**
* acceptEither()用法,用于处理两个阶段的结果
* 1. 此方法【没有返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【能返回】被依赖的异步逻辑中【最先拿到的返回值】
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行acceptEither()
* 5. 此方法【不会造成阻塞】
*/
private static void acceptEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.acceptEither(taskB, info -> {
System.out.println("c:" + LocalDateTime.now());
System.out.println(info);
});
System.out.println(LocalDateTime.now());
}
/**
* applyToEither()用法,用于处理两个阶段的结果
* 1. 此方法【有返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【能返回】被依赖的异步逻辑中【最先拿到的返回值】
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行applyToEither()
* 5. 此方法【不会造成阻塞】
*/
private static void applyToEitherTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
CompletableFuture<String> taskC = taskA.applyToEither(taskB, info -> {
System.out.println("c:" + LocalDateTime.now());
return info;
});
System.out.println(LocalDateTime.now());
// 此方法阻塞后续代码
// System.out.println("数据输出:" + taskC.join());
}
/**
* runAfterBoth()用法,用于处理两个阶段的结果
* 1. 此方法【无返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【不能拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行runAfterBoth()
* 5. 此方法【不会造成阻塞】
*/
private static void runAfterBothTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.runAfterBoth(taskB, () -> {
System.out.println("c:" + LocalDateTime.now());
});
System.out.println(LocalDateTime.now());
}
/**
* thenAcceptBoth()用法,用于处理两个阶段的结果
* 1. 此方法【无返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【能拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenAcceptBoth()
* 5. 此方法【不会造成阻塞】
*/
private static void thenAcceptBothTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
taskA.thenAcceptBoth(taskB, (a, b) -> {
System.out.println("c:" + LocalDateTime.now());
System.out.println((a + b).toUpperCase());
});
System.out.println(LocalDateTime.now());
}
/**
* thenCombine()用法,用于处理两个阶段的结果
* 1. 此方法【有返回值】
* 2. 此方法需要借助【某两个】异步代码逻辑执行
* 3. 此方法【能拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenCombine()
* 5. 此方法会造成后续代码阻塞
*/
private static void thenCombineTest() {
CompletableFuture<String> taskA = CompletableFuture.supplyAsync(() -> {
System.out.println("a:" + LocalDateTime.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task a ";
});
CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> {
System.out.println("b:" + LocalDateTime.now());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task b ";
});
CompletableFuture<String> taskC = taskA.thenCombine(taskB, (a, b) -> {
System.out.println("c:" + LocalDateTime.now());
return (a + b).toUpperCase();
});
System.out.println(LocalDateTime.now());
// System.out.println("数据合并:" + taskC.join());
}
/**
* thenApply()用法
* 1. 此方法【有返回值】
* 2. 此方法需要借助【某一个】异步代码逻辑执行
* 3. 此方法【能拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenApply()
* 5. 此方法会造成阻塞
*/
private static void thenApplyTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
a = a + 1;
System.out.println(a + "1");
return "task a ";
});
CompletableFuture<String> futureB = futureA.thenApply(s -> {
// 下面睡眠解注释,会阻塞后续执行
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
a = a + 1;
System.out.println(a + "2");
return s + "and task b ";
});
CompletableFuture<String> future3 = futureB.thenApply(s -> {
a = a + 1;
System.out.println(a + "3");
return s.toUpperCase();
});
System.out.println("4");
System.out.println("a=" + a);
// 输出最后异步任务返回值,会阻塞后续代码块
// System.out.println(future3.join());
}
/**
* thenRun()用法
* 1. 此方法【没有返回值】
* 2. 此方法需要借助【某一个】异步代码逻辑执行
* 3. 此方法【不能拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenRun()
* 5. 此方法不会造成阻塞
*/
private static void thenRunTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task A";
});
// 放开此睡眠,thenRun()中逻辑会正常执行
// Thread.sleep(5000);
futureA.thenRun(() -> System.out.println("running task B"));
}
/**
* thenAccept()用法
* 1. 此方法【没有返回值】
* 2. 此方法需要借助【某一个】异步代码逻辑执行
* 3. 此方法【可以拿到】被依赖的异步逻辑的返回值
* 4. 如果被依赖的异步逻辑没有执行完,不会等待,且不会执行thenAccept()
* 5. 此方法不会造成阻塞
*/
private static void thenAcceptTest() throws InterruptedException {
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> "task A");
CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "task B";
});
// 放开此睡眠,thenAccept()中逻辑会正常执行
// Thread.sleep(5000);
futureB.thenAccept(b -> {
System.out.println("run task C.");
System.out.println("param:" + b);
});
}
/**
* 场景:异步执行逻辑,并每1秒循环获取返回值,直到异步执行结束返回结果
* 1. join()方法和get()方法:会一直阻塞后续的代码执行
* 2. 如果【join()方法和get()】在timer执行之前,会阻塞循环定时器的执行,所以说在【join()方法和get()方法】以后的代码都会被阻塞
* 3. get(long timeout, TimeUnit unit)方法:经过指定时间直接返回值,会阻塞后续代码一段时间,但是要注意这个方法调用的位置,可以尝试将此方法放到循环定时器之前调用,会与现在结果大不一样
*/
private static void businessExample() throws ExecutionException, InterruptedException, TimeoutException {
// 异步执行逻辑
CompletableFuture<String> stringCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 制造异常
int a = 1 / 0;
return "stringCompletableFuture1";
}).exceptionally(e -> {
// 如果逻辑执行有异常,进入此方法处理异常
throw new RuntimeException();
});
// 循环定时获取结果,获取成功后关闭任务
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 如果异步任务执行结束
if (stringCompletableFuture1.isDone()) {
// 关闭并清理任务
timer.cancel();
System.out.println("done = true,stop task total = " + timer.purge());
// 输出最终结果
System.out.println("getNow():" + LocalDateTime.now() + " " + stringCompletableFuture1.getNow(" END"));
} else {
System.out.println("getNow():" + LocalDateTime.now() + " " + stringCompletableFuture1.getNow(" RUNNING"));
}
}
}, 0, 1000);
System.out.println("get(time):" + stringCompletableFuture1.get(1000L, TimeUnit.MILLISECONDS));
// 代码块
{
System.out.println("join():" + stringCompletableFuture1.join());
System.out.println("get():" + stringCompletableFuture1.get());
}
System.out.println(Thread.currentThread().getName() + "running");
}
}