1.JDK5引入了Future进行异步任务的处理,Future 的接口主要方法有以下几个:

(1)boolean cancel (boolean mayInterruptIfRunning) 取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束

(2)boolean isCancelled () 任务是否已经取消,任务正常完成前将其取消,则返回 true

(3)boolean isDone () 任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true

(4)V get () throws InterruptedException, ExecutionException 等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException

(5) get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计 算超时,将抛出TimeoutException

一般情况下Future 配合Callable 使用,获取异步任务执行的结果,一般使用get()方法设置超时时间,但是在任务执行结束前的这段时间内线程是阻塞的,也就不说异步的了。同时为了获取一般只能采取轮询isDone()方法,这样就显得使用方法很单一,无法适应复杂情况下的异步任务编排。

2.JDK8 引入了CompletableFuture 来进行异步任务的编排,克服了Future的一些缺点,并且且进行了很多扩展。下面对CompletableFuture进行一个小的总结。
3.CompletableFuture 的方法主要有以下几个特点:
(1)以Async结尾的方法都是异步执行的
(2)以run开头的方法一般无返回值,而已supply开头的方法是有返回值的,如 runAsync 和supplyAsync
  (3)   以 then 开头的方法都会在上一个任务执行结束之后执行下一个任务。如 thenApply 和 thenAccept
(4)以Accept结尾的方法均为消耗上个任务执行的结果,无返回值。
(5)以run开头的方法忽略上个任务的执行结果,在上个任务执行结束后执行下个方法。
(6)以Executor 结尾的方法可以自定义线程池,如果没有指定线程池,则会默认在ForkJoinPool.commonPool() 线程池中执行。
4.具体实例
(1) 任务执行类的方法
  • RunAsync 执行异步任务,无返回值
package completablefuture;

import java.util.concurrent.CompletableFuture;

/**
* @Author lizhilong
* @create 2019/11/18 18:07
* @desc
* runAsyn 无返回结果,执行get()方法时,任务被触发。
*/
public class RunAsync {
public static void main(String [] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
System.out.println("Hello");
});
System.out.println("--------------");
try {
future.get();
}catch (Exception e){
e.printStackTrace();
}
}
}
  • SupplyAsync 执行异步任务,有返回值
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/18 18:17
* @desc supplyAsync 方法有返回值,在get()方法后被触发
*/
public class SupplyAsync {
public static void main(String[] args){
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "Hello";
}
}); System.out.println("-------------"); try {
String s = future1.get();
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
}
}
}
  • thenApply 在上个方法执行结束后将返回值作为入参执行下个方法
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/18 18:41
* @desc
* 以Async结尾的方法都会异步执行
* thenApply/thenApplyAsync 会在上个方法执行完之后然后继续执行
*/
public class ThenApply {
public static void main(String[] args) { CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
return "Hello";
}
}).thenApplyAsync(s1 -> {
return s1+"=="+"World";
}); try {
String s = future.get();
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
}
}
}

运行结果

Hello==World
  • ThenAccept 消耗上个任务执行的结果,无返回值。
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/18 19:20
* @desc
* thenAccept 对上个任务产生的结果进行消耗,与ThenApply 不同的是无返回结果
* 所以第二个thenAccept 返回 null
*/
public class ThenAccept {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "hello";
}
}).thenAccept(s1 -> System.out.println(s1+" world"))
.thenAccept(s2-> System.out.println("---"+s2)); try {
future.get();
}catch (Exception e){
e.printStackTrace();
}
}
}

执行结果:

hello world
---null
  • ThenRun 不关心上一步的执行结果,在上一步任务执行结束后执行下一步任务
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 11:44
* @desc thenRun 不关心上一步执行的结果,上一步执行结束后执行下一步
* thenRunAsync 异步执行
*/
public class ThenRun { public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
return "Hello";
}
}).thenRunAsync(new Runnable() {
@Override
public void run() {
System.out.println("World");
}
}); try {
future.get();
}catch (Exception e ){
e.printStackTrace();
} }
}

运行结果:

World
  • ThenApplyWithExecutor 在自定义的线程池执行异步任务
package completablefuture;

import java.util.concurrent.*;

/**
* @Author lizhilong
* @create 2019/11/18 18:59
* @desc
* 自定义线程池的方式来处理有先后顺序的任务
*/
public class ThenApplyWithExecutor { public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool(); CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
return "Hello";
},service).thenApplyAsync(s1->{
return s1 + " World";
},service).thenApplyAsync(s2 ->{
return s2 +" China";
},service); try {
String s = future.get();
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
}finally {
service.shutdownNow();
}
}
}

运行结果:

Hello   World    China
  • runAfterBoth/runAfterBothAsync 在前面任务执行结束后执行新的任务
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 15:33
* @desc runAfterBothAsync 忽略前面任务的执行结果,在前面任务执行结束之后在执行后面的runable任务
*/
public class RunAfterBothAsync {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st1 end");
return "Hello";
}
}).runAfterBothAsync(CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(7000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st2 end");
return "World";
}
}), new Runnable() {
@Override
public void run() {
System.out.println("I LOVE CHINA");
}
}); try {
future.get();
}catch (Exception e){
e.printStackTrace();
}
}
}

运行结果:

st1 end
st2 end
I LOVE CHINA

(2)任务结果消费/组合

  • thenCombine/thenCombineAsync 任务的运行结果进行组合后输出
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 13:40
* @desc thenCombineAsync 将任务的执行结果进行合并后输出
* 最后的合并必操作须等两个任务都执行结束后才可以进行
*/
public class CompletionStage { public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st1 end");
return "Hello";
}
}).thenCombineAsync(
CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(7000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st2 end");
return "World";
}
}
), (r1, r2) -> r1 + " " + r2); try {
String s = future.get();
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
} }

运行结果:

st1 end
st2 end
Hello World
  • ThenAcceptBothAsync 对异步任务的执行结果进行消耗,无返回值
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 14:59
* @desc thenAcceptBothAsync 消费任务的执行结果,无返回值
* 消费动作的执行发生在任务均完成的情况下
*/
public class ThenAcceptBothAsync {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st1 end");
return "Hello";
}
}).thenAcceptBothAsync(CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(7000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("st2 end");
return "World";
}
}) ,(r1, r2) -> System.out.println(r1 +" "+r2)); try {
future.get();
}catch (Exception e){
e.printStackTrace();
}
}
}

运行结果:

st1 end
st2 end
Hello World

(3)根据任务执行完成的先后顺讯进行后续操作

  • applyToEither/applyToEitherAsync 获取最先执行完成的任务的结果
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 15:43
* @desc ApplyToEitherAsync 获取多个任务执行最快的任务结果
*/
public class ApplyToEitherAsync {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st1 end");
return "CHINA";
}
}).applyToEitherAsync(CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(7000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st2 end");
return "AUS";
}
}), (r) -> {
return r;
}).applyToEitherAsync(CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st3 end");
return "UK";
}
}), r1->{
return r1;
}); try {
String s = future.get();
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
} }
}

运行结果:

st3 end
UK
  • acceptEither/acceptEitherAsync 消耗最先执行完的任务的返回结果
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 16:13
* @desc AcceptEitherAsync 消费最先完成的任务返回的结果
*/
public class AcceptEitherAsync { public static void main(String[] args) throws Exception{
CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return "Hello";
}
}).acceptEitherAsync( CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
return "World";
}
}), System.out::println).get();
}
}

运行结果:

Hello
  • RunAfterEither/RunAfterEitherAsync 在前面的任务有任何一个完成后运行
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 18:28
* @desc RunAfterEither 是在前面任务有一个完成以后再去执行的,即最先完成的任务后运行
*
*/
public class RunAfterEither {
public static void main(String[] args) throws Exception{
CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st1 end");
return "Hello";
}
}).runAfterEitherAsync(CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("st2 end");
return "World";
}
}), new Runnable() {
@Override
public void run() {
System.out.println("I LOVE CHINA");
}
}).get();
}
}

运行结果:

st1 end
I LOVE CHINA

(4)任务完成时

  • complete 任务完成后执行后续操作
package completablefuture;

import java.util.concurrent.CompletableFuture;

/**
* @Author lizhilong
* @create 2019/11/18 18:21
* @desc 任务完成以后 执行后续操作
*/
public class Complete { public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
return "Hello";
}); future.complete("world");
System.out.println("----------------");
try {
String s = future.get();
System.out.println(s); }catch (Exception e){
e.printStackTrace();
}
}
}

运行结果:

----------------
world
  • whenCompleteAsync/whenComplete 在前面任务执行完成后执行后续操作,可以获取前面任务的执行结果和异常
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 18:46
* @desc WhenComplete 任务完成后执行相应操作,可以获取上步任务执行的结果或者异常
*/
public class WhenComplete { public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
if (1==2) {
throw new RuntimeException("测试异常");
}
return "Hello";
}
}).whenCompleteAsync((s, e) -> {
System.out.println(s);
System.out.println(e.getMessage());
}); try {
String s = future.get();
System.out.println(s);
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}

运行结果:

Hello
java.lang.NullPointerException

(5)任务执行异常

  • completeExceptionally 任务完成后抛异常
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/18 18:30
* @desc 任务完成以后抛异常
*/
public class CompleteExceptionally {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "Hello";
}
}); future.completeExceptionally( new Exception());
try {
String s = future.get();
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
}
}
}

运行结果:

java.util.concurrent.ExecutionException: java.lang.Exception
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at completablefuture.CompleteExceptionally.main(CompleteExceptionally.java:22)
Caused by: java.lang.Exception
at completablefuture.CompleteExceptionally.main(CompleteExceptionally.java:20)
  • exceptionally 执行任务过程中产生异常
package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 18:35
* @desc 任务产生异常时进行相应操作
*/
public class Exceptionally { public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
int x = 10 / 0;
return "Hello";
}
}).exceptionally(e -> {
System.out.println(e.getMessage());
return "World";
}); try {
String s = future.get();
System.out.println(s);
}catch (Exception e){ }
}
}

运行结果:

java.lang.ArithmeticException: / by zero
World
  • handleAsync/handle 在使用 exceptionally 可以获取异常时的异常,但是无法获取正常执行时的结果
异常:
 public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
if(true){
throw new RuntimeException("测试异常");
}
return "Hello";
}
}).handleAsync((r, e) -> {
if (e != null) {
return e.getMessage();
}
return "World";
}); try {
System.out.println(future.get());
}catch (Exception e){
e.printStackTrace();
}
}

执行结果:

java.lang.RuntimeException: 测试异常

正常:

package completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; /**
* @Author lizhilong
* @create 2019/11/19 18:58
* @desc
*/
public class HandleNormal {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "Hello";
}
}).handleAsync((r, e) -> {
if (e != null) {
return e.getMessage();
}
return "World";
}); try {
System.out.println(future.get());
}catch (Exception e){
e.printStackTrace();
}
} }

执行结果:

World

使用CompletableFuture进行异步任务编排的更多相关文章

  1. 从CompletableFuture到异步编程设计

    从CompletableFuture到异步编程设计,笔者就分为2部分来分享CompletableFuture异步编程设计,前半部分总结下CompletableFuture使用实践,后半部分分享下Com ...

  2. 十九、异步任务编排CompletableFuture

    一.简介 并发编程中我们经常创建异步线程来执行任务.但是,当异步任务之间存在依赖关系时,使得我们开发过程变得更加复杂.比如: 1.线程2依赖于线程1的执行结果 2.线程3依赖于线程1和线程2执行结果的 ...

  3. 使用CompletableFuture实现异步编程

    在开发中会碰到一种场景,如下 Object result1 = service1.func1();//执行80ms Object result2 =service2.func2();//执行50ms ...

  4. Java 8 (10) CompletableFuture:组合式异步编程

    随着多核处理器的出现,提升应用程序的处理速度最有效的方式就是可以编写出发挥多核能力的软件,我们已经可以通过切分大型的任务,让每个子任务并行运行,使用线程的方式,分支/合并框架(java 7) 和并行流 ...

  5. 异步编程CompletableFuture实现高并发系统优化之请求合并

    先说场景: 根据Redis官网介绍,单机版Redis的读写性能是12万/秒,批量处理可以达到70万/秒.不管是缓存或者是数据库,都有批量处理的功能.当我们的系统达到瓶颈的时候,我们考虑充分的压榨缓存和 ...

  6. Java并发包异步执行器CompletableFuture

    前言 CompletableFuture是对Future的一种强有力的扩展,Future只能通过轮询isDone()方法或者调用get()阻塞等待获取一个异步任务的结果,才能继续执行下一步,当我们执行 ...

  7. 《Java 8 in Action》Chapter 11:CompletableFuture:组合式异步编程

    某个网站的数据来自Facebook.Twitter和Google,这就需要网站与互联网上的多个Web服务通信.可是,你并不希望因为等待某些服务的响应,阻塞应用程序的运行,浪费数十亿宝贵的CPU时钟周期 ...

  8. Java8函数之旅 (八) - 组合式异步编程

    前言 随着多核处理器的出现,如何轻松高效的进行异步编程变得愈发重要,我们看看在java8之前,使用java语言完成异步编程有哪些方案. JAVA8之前的异步编程 继承Thead类,重写run方法 实现 ...

  9. CompletableFuture 专题

    /** * @Auther: cheng.tang * @Date: 2019/3/2 * @Description: */ package com.tangcheng.learning.concur ...

随机推荐

  1. [python](Docker SDK)上传镜像到私有仓库(tls、身份认证)

    (Docker SDK)上传镜像到私有仓库(tls.身份认证) API:https://docker-py.readthedocs.io/en/stable/ 环境:python:3.7.3 配置参数 ...

  2. codevs 2977 二叉堆练习1x

    时间限制: 10 s 空间限制: 32000 KB 题目等级 : 白银 Silver       题目描述 Description 已知一个二叉树,判断它是否为二叉堆(小根堆) 输入描述 Input ...

  3. python2.7与3.4共存【win】

    python3并非完全向后兼容python2 方法一: 电脑里有3.4,再安装个2.7 下载地址:https://www.python.org/downloads/windows/ 解释下安装包: W ...

  4. 图片上传(前端显示预览,后端php接收)

    html: <form action="{:Url('do_ls_law_upload')}" method="POST" accept-charset= ...

  5. vue——父组件调用子组件

    <template> <div> child1 </div> </template> <script> export default { n ...

  6. vmvare ubuntu虚拟机固定ip设置

    1.vmvare网络设置 2.window网络设置 3.ubuntu网络设置 先ifconfig 查看ip 已经设置为192.168.122.128 sudo vim /etc/network/int ...

  7. JavaScript this的使用

    当作用域不同时,我们可以将this暂时性的保存下来. 例如: _this =  this.

  8. java线程锁之synchronized

    声明:该博客参考https://www.cnblogs.com/kaituorensheng/p/10079916.html,感谢哥们. 1.Sync.java package com.cn.comm ...

  9. JavaScript日常学习1

    您会经常看到 document.getElementById("id"). 这个方法是 HTML DOM 中定义的. DOM (Document Object Model)(文档对 ...

  10. c# 匿名类型获取值

    代码片段: 读取 new{ ....} 方法1:转换为json对象 dynamic model = SaleOrderServices.GetGiftOrderById(WebHelper.GetQu ...