1. CompletableFuture
CompletableFuture可以进行回调通知、创建异步任务、多个任务前后依赖可以组合处理、对计算速度选最快。
CompletableFuture提供了一种类似于观察者模式的通知方式,可以在任务完成后通知监听方。
CompletableFuture实例化用CompletableFuture.runAsync()和CompletableFuture.supplyAsync()。
public class demo04 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
// 无返回值
// CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(new MyThread4(), threadPool);
// try {
// System.out.println(completableFuture.get());
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// } catch (ExecutionException e) {
// throw new RuntimeException(e);
// }
// 有返回值
CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello World";
});
try {
System.out.println(stringCompletableFuture.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
// 有返回值
CompletableFuture completableFuture = CompletableFuture.supplyAsync(new MyThread5(), threadPool);
try {
System.out.println(completableFuture.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
threadPool.shutdown();
}
}
class MyThread5 implements Supplier {
@Override
public Object get() {
return "Hello Apple";
}
}
class MyThread4 implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("Hello World");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
2. whenCompleted与exceptionally用法
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
try {
CompletableFuture.supplyAsync(()->{
int num = 10/0;
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return num;
}, threadPool).whenComplete((v,e)->{
if(e == null) {
System.out.println("Result is " + v);
}
}).exceptionally(e->{
e.printStackTrace();
System.out.println(e.getCause() + e.getMessage());
return null;
});
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
threadPool.shutdown();
}
System.out.println("Main is completed");
}
链式调用
public class demo06 {
public static void main(String[] args){
Stu stu = new Stu();
stu.setId("1818").setName("Jack");
System.out.println(stu.toString());
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
return "Hello World";
});
// 编译时,必须设置对于异常的处理
try {
System.out.println(completableFuture.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
// 可以不进行设置对于异常的处理
String join = completableFuture.join();
}
}
@AllArgsConstructor
@NoArgsConstructor
// 允许链式调用
@Accessors(chain = true)
@Setter
@Getter
@ToString
class Stu {
private String id;
private String name;
}
CompletableFuture的例子。
public class demo07 {
public static List<ShopMall> list = Arrays.asList( new ShopMall("taobao")
,new ShopMall("jd")
,new ShopMall("pdd")
,new ShopMall("dangdang"));
public static void main(String[] args){
System.out.println(extracted("mysql"));
}
private static List<String> extracted(String productName) {
List<String> stringList = list.stream()
// 使用CompletableFuture实现多线程异步
.map(shopMall -> CompletableFuture.supplyAsync(() -> String.format(productName + "'s price in %s is %.2f", shopMall.getShop(), shopMall.getPrice(productName))))
.collect(Collectors.toList()).stream().map(completableFuture -> completableFuture.join()).collect(Collectors.toList());
return stringList;
}
}
@AllArgsConstructor
class ShopMall {
@Getter
String shop;
public Double getPrice(String name) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return ThreadLocalRandom.current().nextDouble()*2 + name.charAt(0);
}
}
CompletableFuture的用法:
public class demo08 {
public static void main(String[] args) {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "Hello World";
});
// 需要抛异常
// System.out.println(completableFuture.get());
// 无需抛异常
// System.out.println(completableFuture.join());
// 子线程没执行完, 就返回getNow的参数
// System.out.println(completableFuture.getNow("Absent"));
// 子线程未执行完, complete返回true, join返回complete的参数
System.out.println(completableFuture.complete("Absent") + ":" + completableFuture.join());
}
}
3. CompletableFuture常用函数
对于执行结果的处理。
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
CompletableFuture.supplyAsync(()->{
return 1;
}, threadPool)
// 前一步结果作为返回值,有异常则停止
.thenApply(f->{
System.out.println("thenApply");
return f+1;
})
// 可以带着异常,继续执行
// .handle((v, e)->{
// System.out.println("handel");
// int num = 10/0;
// return v+1;
// })
// 无返回值
.thenAccept(v->{
System.out.println("thenAccept");
System.out.println(v);
})
// 无参数与返回值
.thenRun(()->{
System.out.println("thenRun");
});
threadPool.shutdown();
}
CompletableFuture异步方法与applyToEither选取执行速度更快的线程。
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
// thenRunAsync会让后续线程使用默认线程池
CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName());
return 1;
}, threadPool)
// 前一步结果作为返回值,有异常则停止
.thenRunAsync(()->{
System.out.println(Thread.currentThread().getName());
System.out.println("Hello");
})
.thenRunAsync(()->{
System.out.println(Thread.currentThread().getName());
System.out.println("Hello");
})
.thenRun(()->{
System.out.println(Thread.currentThread().getName());
System.out.println("Hello");
});
CompletableFuture<String> completableFutureA = CompletableFuture.supplyAsync(() -> {
System.out.println("A comes in");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "A";
});
CompletableFuture<String> completableFutureB = CompletableFuture.supplyAsync(() -> {
System.out.println("B comes in");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "B";
});
// 选用执行更快的线程
CompletableFuture<String> completableFuture = completableFutureA.applyToEither(completableFutureB, v -> {
return "win is " + v;
});
System.out.println(completableFuture.join());
// 将结果联合
CompletableFuture<String> combine = completableFutureA.thenCombine(completableFutureB, (a, b) -> {
return a + b;
});
System.out.println(combine.join());
threadPool.shutdown();
}