常见实现线程方法:
- 继承thread类
- 实现runnable接口
上述方式不能获得返回值,若想获得返回值其常见方式为实现callable接口,用Future描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种阻塞的方式显然和我们的异步编程的初衷相违背。
为了解决这个问题,Java8加入了CompletableFuture实现了CompletionStage和Future接口。
Java8之前的Future示例:
if (!CollectionUtils.isEmpty(servers)) {
servers.stream().forEach(x->
resultList.add(executorService.submit(() -> new X86CheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call())));
}
//创建power资源监测任务类置于线程池
Page<PowerServerDTO> powerDTOPage = powerServerApplyService.listAllServerDTOS();
List<PowerServerDTO> powers = powerDTOPage.getRecords();
if (!CollectionUtils.isEmpty(servers)) {
powers.stream().forEach(x->
resultList.add(executorService.submit(() -> new PowerCheckThread(x.getId(),x.getId(), x.getName(), x.getStatus(), checkDto, sysUser).call())));
}
resultList.stream().forEach(x-> {
try {
if (x.get().getFlag() == true) {
checkResponseDTOList.add(x.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
使用CompletableFuture改写示例:
if (!CollectionUtils.isEmpty(servers)) {
servers.stream().forEach(x->{
CheckResponseDTO checkResponse = CompletableFuture.supplyAsync(() -> new X86CheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call(), executorService).
whenComplete((s, e) -> logger.info("X86主机 "+x.getServerName()+"检测完成")).join();
checkResponseDTOList.add(checkResponse);
});
}
//创建power资源监测任务类置于线程池
Page<PowerServerDTO> powerDTOPage = powerServerApplyService.listAllServerDTOS();
List<PowerServerDTO> powers = powerDTOPage.getRecords();
if (!CollectionUtils.isEmpty(powers)) {
powers.stream().forEach(x->{
CheckResponseDTO checkResponse = CompletableFuture.supplyAsync(() -> new PowerCheckThread(x.getId(), x.getResourceId(), x.getServerName(), x.getStatus(), checkDto, sysUser).call(), executorService).
whenComplete((s, e) -> logger.info("power主机 "+x.getName()+"检测完成")).join();
checkResponseDTOList.add(checkResponse);
});
}
List<CheckResponseDTO> collect = checkResponseDTOList.stream().filter(x -> x.getFlag() == true).collect(Collectors.toList());
CompletableFuture的api介绍:
/**
* 转换api
* public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
* thenApply它的入参是上一个阶段计算后的结果,返回值是经过转化后结果。
*/
@Test
public void testThenApply() {
String join = CompletableFuture.supplyAsync(() -> "hello").thenApply(s -> s + "world").join();
System.out.println(join);
}
/**
* 消耗api
* public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);
thenAccept是针对结果进行消耗,因为他的入参是Consumer,有入参无返回值。
*/
@Test
public void testThenAccept() {
CompletableFuture.supplyAsync(() -> "hello ").thenAccept(s -> System.out.println(s + "world"));
}
/**
* public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
* thenRun它的入参是一个Runnable的实例,表示当得到上一步的结果时的操作。但是对上一步的计算结果不关心,执行下一个操作。
*/
@Test
public void testThenRun() {
CompletableFuture.supplyAsync(()->"hello ").thenRun(()-> System.out.println("hello Mr.Lee"));
}
/**
* public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);
* 结合两个CompletionStage的结果,进行转化后返回
*/
@Test
public void testCombine() {
String join = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "world";
}), (s1, s2) -> s1 + s2).join();
System.out.println(join);
}
/**
* public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor);
* thenAcceptBoth结合两个CompletionStage的结果,进行消耗,它需要原来的处理返回值,并且other代表的CompletionStage也要返回值之后,利用这两个返回值,进行消耗。
*/
@Test
public void testThenAcceptBoth() {
CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).thenAcceptBoth(CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "world";
}), (s1, s2) -> System.out.println(s1 + " " + s2));
while (true){}
}
/**
* public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
* runAfterBoth在两个CompletionStage都运行完执行。不关心这两个CompletionStage的结果,只关心这两个CompletionStage执行完毕,之后在进行操作(Runnable)。
*/
@Test
public void testRunAfterBoth() {
CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}).runAfterBothAsync(CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "world";
}),()-> System.out.println("我来啦"));
}
/**
* public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);
* 两个CompletionStage,谁计算的快,我就用那个CompletionStage的结果进行下一步的转化操作。
*/
@Test
public void testApplyToEither() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}), s -> s).join();
System.out.println(result);
}
/**
* public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);
* 两个CompletionStage,谁计算的快,我就用那个CompletionStage的结果进行下一步的消耗操作。
*/
@Test
public void acceptEither() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).acceptEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}), System.out::println);
while (true){}
}
/**
* public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
* 两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)
*/
@Test
public void runAfterEither() {
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s1";
}).runAfterEither(CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "s2";
}), () -> System.out.println("hello world"));
while (true) {
}
}
/**
* public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn);
* 当运行时出现了异常,可以通过exceptionally进行补偿
*/
@Test
public void testExceptionally() {
String join = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (true) {
throw new RuntimeException("简单测一下异常");
}
return "s";
}).exceptionally(s -> {
System.out.println(s.getMessage());
return "hello world";
}).join();
System.out.println(join);
}
/**
* public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,Executor executor);
* 当运行完成时,对结果的记录。这里的完成时有两种情况,一种是正常执行,返回值。
* 另外一种是遇到异常抛出造成程序的中断。这里为什么要说成记录,因为这几个方法都会返回CompletableFuture,
* 当Action执行完毕后它的结果返回原始的CompletableFuture的计算结果或者返回异常。所以不会对结果产生任何的作用。
*/
@Test
public void whenComplete() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "s1";
}).whenComplete((s, t) -> {
System.out.println(s);
System.out.println(t.getMessage());
}).exceptionally(e -> {
System.out.println(e.getMessage());
return "hello world";
}).join();
System.out.println(result);
}
/**
* public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);
* 运行完成时,对结果的处理。这里的完成时有两种情况,一种是正常执行,返回值。
* 另外一种是遇到异常抛出造成程序的中断。
*/
@Test
public void handle() {
String result = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//出现异常
if (1 == 1) {
throw new RuntimeException("测试一下异常情况");
}
return "s1";
}).handle((s, t) -> {
if (t != null) {
return "hello world";
}
return s;
}).join();
System.out.println(result);
}