CompletableFuture(异步编程)
CompletableFuture的由来
CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力,使Java在处理多任务的协同工作时更加顺畅便利。
代码示例(一)
thenCombine(合并)
public class Futrue {
public static void main(String[] args) {
System.out.println("小范来到了餐厅");
System.out.println("小范点了 番茄炒蛋+ 一碗米饭");
CompletableFuture<String> data = CompletableFuture.supplyAsync(() -> {
System.out.println("厨师开始炒菜");
work(5);
return "番茄炒蛋";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
System.out.println("服务员开始蒸米饭");
work(2);
return "米饭";
}), (food1, food2) -> {
return food1 + food1;
});
System.out.println("小范先打一把游戏等饭做好");
System.out.println(data.join()+"饭做好了。小范开始吃饭");
System.out.println("我吃完饭了");
}
//开始工作 workTime:工作时间
public static void work(Integer workTime) {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
小范来到了餐厅
小范点了 番茄炒蛋+ 一碗米饭
厨师开始炒菜
服务员开始蒸米饭
小范先打一把游戏等饭做好
服务员蒸完米饭
厨师炒完菜了
番茄炒蛋番茄炒蛋饭做好了。小范开始吃饭
我吃完饭了
这里我们发现厨师炒菜和服务员蒸米饭是同时进行的,最后并把两个线程的结果合并并返回
代码示例(二)
thenCompose(连接)
public class Futrue {
public static void main(String[] args) {
System.out.println("小范来到了餐厅");
System.out.println("小范点了 番茄炒蛋+ 一碗米饭");
CompletableFuture<String> data = CompletableFuture.supplyAsync(() -> {
System.out.println("厨师开始炒菜");
work(5);
System.out.println("厨师炒菜完成");
return "番茄炒蛋";
}).thenCompose(dish -> CompletableFuture.supplyAsync(() -> {
System.out.println("服务员开始打菜");
work(2);
System.out.println("服务员打菜完成");
return dish + "米饭";
}));
System.out.println("小范先打一把游戏等饭做好");
System.out.println(data.join()+"饭做好了。小范开始吃饭");
System.out.println("我吃完饭了");
}
//开始工作 workTime:工作时间
public static void work(Integer workTime) {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
小范来到了餐厅
小范点了 番茄炒蛋+ 一碗米饭
厨师开始炒菜
小范先打一把游戏等饭做好
厨师炒菜完成
服务员开始打菜
服务员打菜完成
番茄炒蛋米饭饭做好了。小范开始吃饭
我吃完饭了
这里我们会发先厨师炒菜和服务员蒸米饭是顺序执行的,最后由服务员把菜和饭端给客人
代码示例(三)
thenApply 和thenCompose很相像
public class Futrue {
public static void main(String[] args) {
System.out.println("小范吃完饭了");
System.out.println("小范结账,要求开发票");
//场景:要求收款的和发票的是同一个人
CompletableFuture<String> data = CompletableFuture.supplyAsync(() -> {
System.out.println("服务员" + Thread.currentThread().getName() + "收款500");
work(5);
System.out.println("服务员" + Thread.currentThread().getName() + "收完款");
return "500";
}).thenApply(money -> {
System.out.println("开票员" + Thread.currentThread().getName() + "开了"+money+"大小的发票");
work(5);
System.out.println("开票员" + Thread.currentThread().getName() + "开完了票");
return "500元发票";
});
System.out.println("小范接了电话准备回家玩游戏");
System.out.println(data.join() + "开好了。");
System.out.println("小范回家");
}
//开始工作 workTime:工作时间
public static void work(Integer workTime) {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
小范吃完饭了
小范结账,要求开发票
服务员ForkJoinPool.commonPool-worker-9收款500
小范接了电话准备回家玩游戏
服务员ForkJoinPool.commonPool-worker-9收完款
开票员ForkJoinPool.commonPool-worker-9开了500大小的发票
开票员ForkJoinPool.commonPool-worker-9开完了票
500元发票开好了。
小范准备回家
代码示例(四)
applyToEither :获取执行速度最快的异步方法并返回结果
public class Futrue {
public static void main(String[] args) {
System.out.println("小范走出食堂,来到公交站");
System.out.println("等待1路汽车 或者 2路汽车");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("1路汽车正在赶来");
work(5);
return "1路汽车";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println("2路汽车正在赶来");
work(10);
return "2路汽车";
}), fisrtMethod -> fisrtMethod);
System.out.println(completableFuture.join()+"汽车先来,坐上回家");
}
//开始工作 workTime:工作时间
public static void work(Integer workTime) {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
小范走出食堂,来到公交站
等待1路汽车 或者 2路汽车
1路汽车正在赶来
2路汽车正在赶来
1路汽车汽车先来,坐上回家
示例代码(五)
exceptionally:异步编程异常处理
public class Futrue {
public static void main(String[] args) {
System.out.println("小范走出食堂,来到公交站");
System.out.println("等待1路汽车 或者 2路汽车");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("1路汽车正在赶来");
work(5);
return "1路汽车";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println("2路汽车正在赶来");
work(10);
return "2路汽车";
}), fisrtMethod -> {
if (fisrtMethod.equals("1路汽车")) {
throw new RuntimeException("撞树了");
}
return fisrtMethod;
}).exceptionally(e -> {
System.out.println(e.getMessage());
System.out.println("小白叫了出租车回家");
return "出租车";
});
System.out.println(completableFuture.join() + "汽车先来,坐上回家");
}
//开始工作 workTime:工作时间
public static void work(Integer workTime) {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
小范走出食堂,来到公交站
等待1路汽车 或者 2路汽车
1路汽车正在赶来
2路汽车正在赶来
java.lang.RuntimeException: 撞树了
小白叫了出租车回家
出租车汽车先来,坐上回家