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. BZOJ 3073: [Pa2011]Journeys Dijkstra+线段树优化建图

    复习一下线段树优化建图:1.两颗线段树的叶子节点的编号是公用的. 2.每次连边是要建两个虚拟节点 $p1,p2$ 并在 $p1,p2$ 之间连边. #include <bits/stdc++.h ...

  2. memcpy 与strcpy的区别

      C/C++中mencpy的代码实现:https://www.cnblogs.com/goul/p/10191705.html C/C++中strcpy的代码实现:https://www.cnblo ...

  3. 自定义MessageConverter--消息转换器

    我们在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或者指定自定义的转换器,就需要用到MessageConverter 自定义常用转换器:MessageC ...

  4. js保留二位小数

    js保留小数常用有三种方法,可根据实际情况选择 方法一:使用toFixed保留两位小数 自带四舍五入与补位 var num1 = 55.3715; console.log(num1.toFixed(2 ...

  5. 05.用两个栈实现队列 Java

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 进栈: 直接进stack1 出栈: 若stack2不为空,则出栈. 否则,当stack1不为空时, ...

  6. iOS 修改打包后的.ipa应用名字

    一.修改应用的名字 二.重新签名 下面详细介绍介绍两个步骤: 1.修改应用的名字: 1).解压.ipa文件,在Payload文件夹下有一个.app文件(如下图:)选中.app文件,右键点击“显示包内容 ...

  7. 代码实现:当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版

    package com.loaderman.test; import java.io.BufferedReader; import java.io.FileReader; import java.io ...

  8. lucene 快速入门

    日常开发中,相信大家经常会用like去匹配一些数据,同时我们也知道,like往往会导致全表扫描,当数据量越来越大的时候,我们会纠结于 数据库的龟速查找,此时我们必须另寻蹊跷,这时lucene就可以大显 ...

  9. Mybaits-Maven项目之逆向工程(代码自动生成)

    1.添加maven插件,让maven环境支持mybatis-generator组件 在pom.xml里面添加如下代码: <project xmlns="http://maven.apa ...

  10. 小D课堂 - 零基础入门SpringBoot2.X到实战_汇总

    第1节零基础快速入门SpringBoot2.0 小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_1.SpringBoot2.x课程介绍和高手系 ...