CompletableFuture的使用例子
1. CompletableFuture的介绍
在Java8时被引入,在包java.util.concurrent下,是Java多线程编程中的一个类,扩展了Future中很多功能,CompletableFuture是一个实现了接口Future和CompletionStage的类。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
2. Future与CompletableFuture对比
1 Future#get阻塞方法,影响后续代码执行,CompletableFuture可以设置callback的方式处理:CompletableFuture#thenAcceptAsync
2 CompletableFuture可以组合多个CompletableFuture:CompletableFuture#thenCompose、anyof
3 CompletableFuture优雅处理线程异常:CompletableFuture#handle、exceptionally
4 CompletableFuture可以手动设置为完成,即一个线程处理任务的时间过长,可以手动设置为完成,并设置返回值:CompletableFuture#complete
3. CompletableFuture常用方法
3.1. CompletableFuture#runAsync
/**
* @see CompletableFuture#runAsync(Runnable) 接收一个Runnable参数
*/
@Test
public void runAsyncTest() {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
System.out.println(getCurrentThreadName() + "------runSync method");
});
// ForkJoinPool.commonPool-worker-9------runSync method
}
3.2. CompletableFuture#supplyAsync
/**
* @throws ExecutionException
* @throws InterruptedException
* @see CompletableFuture#supplyAsync(Supplier) 接受一个Supplier参数
*/
@Test
public void supplyAsyncTest() throws ExecutionException, InterruptedException {
CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> "return a string of supplyAsync method");
System.out.println(stringCompletableFuture.get());
// return a string of supplyAsync method
}
3.3. CompletableFuture#thenAccept
/**
* @see CompletableFuture#thenAccept(Consumer) runAync或者supplyAsync执行完后进行的操作(callback)
*/
@Test
public void thenAcceptTest() {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
System.out.println(getCurrentThreadName() + "------runSync method");
}).thenAccept((consumer) -> {
System.out.println(getCurrentThreadName() + "------thenAccept method");
});
System.out.println(getCurrentThreadName() + " End");
// ForkJoinPool.commonPool-worker-9------runSync method
// main------thenAccept method
// main End
}
3.4. CompletableFuture#thenAcceptAsync
/**
* @see CompletableFuture#thenAcceptAsync(Consumer) 异步callback
*/
@Test
public void thenAcceptAsyncTest() throws InterruptedException {
AtomicReference<Thread> threadAtomicReference = new AtomicReference<>();
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
threadAtomicReference.set(Thread.currentThread());
System.out.println(getCurrentThreadName() + "------runSync method");
}).thenAcceptAsync((consumer) -> {
System.out.println(getCurrentThreadName() + "------thenAccept method");
getCurrentThread().notifyAll();
});
TimeUnit.SECONDS.sleep(1);
System.out.println(getCurrentThreadName() + " End");
// ForkJoinPool.commonPool-worker-9------runSync method
// ForkJoinPool.commonPool-worker-9------thenAccept method
// main End
}
3.5. CompletableFuture#thenApply
/**
* @see CompletableFuture#thenApply(Function)
*/
@Test
public void thenApply() {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> "supplyAsync method")
.thenApply((s) -> s + " -> theApply method")
.thenAccept(System.out::println);
// supplyAsync method -> theApply method
}
3.6. CompletableFuture#thenCompose
/**
* @see CompletableFuture#thenCompose(Function) 作为两个CompletableFuture组合使用 这里的Function<? super T, ?
* extends CompletionStage<U>> T要转换成CompletionStage对应的子类? extends
* CompletionStage<U>,比如另一个CompletableFuture#supplyAsync返回值就是.
*/
@Test
public void thenComposeTest() {
CompletableFuture.supplyAsync(() -> getCurrentThreadName() + ": supplyAsync -> ")
.thenCompose(
(s) ->
CompletableFuture.supplyAsync(
() -> s + getCurrentThreadName() + "---theApply method -> "))
.thenAccept((f) -> System.out.println(f + getCurrentThreadName() + "---thenAccept"));
// ForkJoinPool.commonPool-worker-9: supplyAsync -> ForkJoinPool.commonPool-worker-9---theApply
// method -> main---thenAccept
}
3.7. CompletableFuture#thenCombine
/**
* @see CompletableFuture#thenCombine(CompletionStage, BiFunction)
* 等两个CompletableFuture完成后,对它们的返回值进行处理,也是对多个CompletableFuture进行组合
*/
@Test
public void thenCombineTest() {
CompletableFuture.supplyAsync(() -> getCurrentThreadName() + ": the first return value")
.thenCombine(
CompletableFuture.supplyAsync(
() -> getCurrentThreadName() + ": the second return value"),
(p1, p2) -> {
if (StringUtils.hasText(p1) && StringUtils.hasText(p2)) {
return p1 + "\n" + p2 + "\n";
} else if (StringUtils.hasText(p1)) {
return p1;
} else if (StringUtils.hasText(p2)) {
return p2;
} else {
return null;
}
})
.thenAccept((f) -> System.out.println(f + getCurrentThreadName() + "---thenAccept"));
// ForkJoinPool.commonPool-worker-9: the first return value
// ForkJoinPool.commonPool-worker-9: the second return value
// main---thenAccept
}
3.8. CompletableFuture#allOf
/**
* 多个CompletableFuture,如果都结束了,就可以获得它们的返回值,进行处理
*
* @throws InterruptedException
* @see CompletableFuture#allOf(CompletableFuture[])
*/
@Test
public void allOfTest() throws InterruptedException {
CompletableFuture<String> diligent =
CompletableFuture.supplyAsync(
() -> {
try {
TimeUnit.MICROSECONDS.sleep(100);
return getCurrentThreadName() + ": be a diligent man.";
} catch (InterruptedException e) {
e.printStackTrace();
return getCurrentThreadName() + ": missing diligent";
}
}); CompletableFuture<String> studious =
CompletableFuture.supplyAsync(
() -> {
try {
TimeUnit.MICROSECONDS.sleep(100);
return getCurrentThreadName() + ": be a studious man.";
} catch (InterruptedException e) {
e.printStackTrace();
return getCurrentThreadName() + ": missing studious";
}
}); CompletableFuture<String> savvy =
CompletableFuture.supplyAsync(
() -> {
try {
TimeUnit.MICROSECONDS.sleep(100);
return getCurrentThreadName() + ": be a savvy man.";
} catch (InterruptedException e) {
e.printStackTrace();
return getCurrentThreadName() + ": missing savvy";
}
}); CompletableFuture<List<String>> allOf =
CompletableFuture.allOf(savvy, diligent, studious)
.thenApply(
(n) -> {
return Stream.of(savvy, diligent, studious)
.map(
(completableFuture) -> {
try {
// get every return string
return completableFuture.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return e.toString();
}
})
.collect(Collectors.toList());
}); TimeUnit.SECONDS.sleep(1);
// if you want to output every string (and above code of block of "thenApply" also can
// forEach(System.out::println))
allOf.thenAccept((stringList) -> stringList.forEach(System.out::println));
// ForkJoinPool.commonPool-worker-11: be a savvy man.
// ForkJoinPool.commonPool-worker-9: be a diligent man.
// ForkJoinPool.commonPool-worker-2: be a studious man. }
3.9. CompletableFuture#anyOf
/**
* anyOf方法,组合多个future,只要有一个结束就完成
*
* @see CompletableFuture#anyOf(CompletableFuture[])
*/
@Test
public void anyOfTest() {
CompletableFuture<People> peopleCompletableFuture = CompletableFuture.supplyAsync(People::new);
CompletableFuture<String> stringCompletableFuture =
CompletableFuture.supplyAsync(() -> "a string");
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> 1); CompletableFuture.anyOf(
stringCompletableFuture, peopleCompletableFuture, integerCompletableFuture)
.thenAccept(System.out::println);
}
3.10. CompletableFuture#handle
/**
* handle方法无论是否发生异常,都会调用,可以在这里处理异常,另一个处理异常的方式:{@link #exceptionallyTest()}
*
* @see CompletableFuture#handle(BiFunction)
* @throws InterruptedException
*/
@Test
public void handleTest() throws InterruptedException {
final String string = "";
CompletableFuture.supplyAsync(
() -> {
if (!StringUtils.hasText(string)) {
throw new NullPointerException("string is null");
}
return string;
})
.handle(
(s, t) -> {
if (t != null) {
// log.error("handle method", t);
log.error("handle method");
}
return s;
}); // For junit main thread stop after ForkJoinPool thread
TimeUnit.SECONDS.sleep(1);
System.out.println(getCurrentThreadName() + " stop");
// 18:30:47.837 [ForkJoinPool.commonPool-worker-9] ERROR
// com.xy.java.basic.demos.completablefuture.CompletableFutureTest - handle method
// main stop
}
3.11. Completable#exceptionally
/**
* 当发生异常时,进入exceptionally方法,另一个处理异常的方式:{@link #handleTest()}
*
* @see CompletableFuture#exceptionally(Function)
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public void exceptionallyTest() throws InterruptedException, ExecutionException {
final String string = "";
CompletableFuture.supplyAsync(
() -> {
if (!StringUtils.hasText(string)) {
throw new NullPointerException("string is null");
}
return Optional.ofNullable(string);
})
.exceptionally(
(t) -> {
// log.error("exceptionally method", t);
log.error("exceptionally method");
return Optional.empty();
}); // For junit main thread stop after ForkJoinPool thread
TimeUnit.SECONDS.sleep(1);
System.out.println(getCurrentThreadName() + " stop");
// 18:27:29.451 [ForkJoinPool.commonPool-worker-9] ERROR
// com.xy.java.basic.demos.completablefuture.CompletableFutureTest - exceptionally method
// main stop
}
3.12. CompletableFuture#complete
/**
* 手动完成一个耗时很长的Future,并且设置默认值
*
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public void completeTest() throws InterruptedException, ExecutionException {
CompletableFuture<Boolean> runAsync =
CompletableFuture.supplyAsync(
() -> {
try {
TimeUnit.SECONDS.sleep(3);
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}); TimeUnit.SECONDS.sleep(1);
// 手动设置Future为完成状态并设置默认值
runAsync.complete(false); System.out.println(runAsync.get());
// false TimeUnit.SECONDS.sleep(5);
}
3.13. 注:Junit测试类中的公共方法
private Thread getCurrentThread() {
return Thread.currentThread();
}
private String getCurrentThreadName() {
return getCurrentThread().getName();
}
4. thenApply与thenCompose的区别
4.1. 用thenApply方法来组合两个CompletableFuture
/**
* @see CompletableFuture#thenApply(Function)
* 如果想用thenApply方法来组合两个CompletableFuture,看起来会非常不优雅,所以组合多个CompletableFuture推荐使用<b>CompletableFuture#thenCompose</b>
*/
@Test
public void thenApplyNeedReturnCompletionStageTest() {
CompletableFuture<Void> voidCompletableFuture =
CompletableFuture.supplyAsync(() -> getCurrentThreadName() + "---supplyAsync method -> ")
.thenApply(
(s) ->
CompletableFuture.supplyAsync(
() -> s + getCurrentThreadName() + "---theApply method -> "))
.thenAccept(
(c) ->
c.thenAccept(
(f) -> System.out.println(f + getCurrentThreadName() + "---thenAccept")));
// ForkJoinPool.commonPool-worker-9---supplyAsync method ->
// ForkJoinPool.commonPool-worker-9---theApply method -> main---thenAccept
}
4.2. 用thenCompose方法来组合两个CompletableFuture
/**
* @see CompletableFuture#thenCompose(Function) 作为两个CompletableFuture组合使用 这里的Function<? super T, ?
* extends CompletionStage<U>> T要转换成CompletionStage对应的子类? extends
* CompletionStage<U>,比如另一个CompletableFuture#supplyAsync返回值就是.
*/
@Test
public void thenComposeTest() {
CompletableFuture.supplyAsync(() -> getCurrentThreadName() + ": supplyAsync -> ")
.thenCompose(
(s) ->
CompletableFuture.supplyAsync(
() -> s + getCurrentThreadName() + "---theApply method -> "))
.thenAccept((f) -> System.out.println(f + getCurrentThreadName() + "---thenAccept"));
// ForkJoinPool.commonPool-worker-9: supplyAsync -> ForkJoinPool.commonPool-worker-9---theApply
// method -> main---thenAccept
}
5. CompletableFuture常用方法总结
1 runAsync接收的Runnable参数,supplyAsync接收的Supplier参数
2 thenAccept与thenAcceptAsync的区别在于:该callback方法是否在当前线程中执行(更具体的例子见前面的代码中的运行结果)
3 thenApply与thenCompose主要区别在于组合多个CompletableFuture
4 其他的方法如上面的代码例子所示
CompletableFuture的使用例子的更多相关文章
- CompletableFuture引入
一.Future介绍 Future以前我们如果有个方法action执行,比如去数据库中查询数据.上传一个文件等,这个方法执行10分钟,调用者就需要等10分钟.基于此,调用者可以先执行action,返回 ...
- java8中CompletableFuture的使用介绍
既然CompletableFuture类实现了CompletionStage接口,首先我们需要理解这个接口的契约.它代表了一个特定的计算的阶段,可以同步或者异步的被完成.你可以把它看成一个计算流水线上 ...
- Vertx简介
今天看了一篇很不错的关于Vertx的简介,转载下. 原文链接:http://www.csdn.net/article/2015-12-21/2826533?utm_source=tuicool& ...
- Monad 在实际开发中的应用
版权归作者所有,任何形式转载请联系作者. 作者:tison(来自豆瓣) 来源:https://www.douban.com/note/733279598/ Monad 在实际开发中的应用 不同的人会从 ...
- Java CompletableFuture 详解
Future是Java 5添加的类,用来描述一个异步计算的结果.你可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel方法停止任务的执 ...
- CompletableFuture基本用法
异步计算 所谓异步调用其实就是实现一个可无需等待被调用函数的返回值而让操作继续运行的方法.在 Java 语言中,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结 ...
- 从CompletableFuture到异步编程设计
从CompletableFuture到异步编程设计,笔者就分为2部分来分享CompletableFuture异步编程设计,前半部分总结下CompletableFuture使用实践,后半部分分享下Com ...
- JAVA8给我带了什么——Optional和CompletableFuture
不管是JAVA,还是.NET.我们常常会看到空异常(NullPointerException).这种异常都是在运行的过程中出现.往往是变量是一个null值.但是你引用这个变量的后继字段或是方法.所以我 ...
- Java8 CompletableFuture
http://colobu.com/2016/02/29/Java-CompletableFuture/ http://www.deadcoderising.com/java8-writing-asy ...
随机推荐
- Spark SQL源码解析(二)Antlr4解析Sql并生成树
Spark SQL原理解析前言: Spark SQL源码剖析(一)SQL解析框架Catalyst流程概述 这一次要开始真正介绍Spark解析SQL的流程,首先是从Sql Parse阶段开始,简单点说, ...
- [javascript] js实现小数的算术运算方法
/** ** 加法函数,用来得到精确的加法结果 ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精确的加法结果. ** 调用:accAdd(arg ...
- [YII2] COOKIE的操作使用
PHPcookie的设置 setcookie('username',$data['username'],time()+3600*24*7); YII2cookie的设置 $cookies = Yii: ...
- JQ获取select上的option的data-start和data-id
来源:https://zhidao.baidu.com/question/692142321436883524.html 静态的写法: 用jq的attr()函数,如: HTML: <select ...
- js事件冒泡于事件捕获
事件冒泡 事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上(从最深节点开始,向上传播事件)的触发事件 //例子 <div id="pa ...
- ubuntu server 18.04 网络配置
从17.10开始放弃在/etc/network/interfaces里固定IP的配置 配置文件是:/etc/netplan/50-cloud-init.yaml .用缩进来表示层级关系 冒号之后要有个 ...
- Netty(三):IdleStateHandler源码解析
IdleStateHandler是Netty为我们提供的检测连接有效性的处理器,一共有读空闲,写空闲,读/写空闲三种监测机制. 将其添加到我们的ChannelPipline中,便可以用来检测空闲. 先 ...
- extend()和append()区别
extend()和append()都可以用来添加. 例: a = [1,2,3,4,5,6] b = [7,8,9,10] c = {'aa':123,'bb':456,'cc':789} 1. ...
- CompressIt
结构 压缩软件的核心在于压缩算法.基于Huffman编码的压缩算法思路: 以二进制方式读取源文件,按照每8bits作为一个字符: 统计每个字符的出现频率即为叶子结点的权值,按照Huffman算法得到每 ...
- mysql-case..when知识点总结
case...when..有两种语法: 第一种: case case_value when when_value then statement_list [when when_value the ...