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. 【Java Web】IDEA如何创建及配置Web项目(多图)

    正文之前 在学习Java Web时,第一个遇到的问题就是如何创建或配置Web项目了,今天,就用IntelliJ IDEA 来进行Web项目配置: 创建Web项目 配置web项目 正文 创建Web项目 ...

  2. BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡 概率与期望+高斯消元

    这个还挺友好的,自己相对轻松能想出来~令 $f[i]$ 表示起点到点 $i$ 的期望次数,则 $ans[i]=f[i]\times \frac{p}{q}$ #include <cmath> ...

  3. linux文本处理三剑客之 grep

    文本处理无非是对文本内容做查看.修改等操作.Linux三剑客: grep.sed 和 awk 命令. 处理文本内容,用 Vim 编辑器不是很好吗?Vim 允许我们使用键盘.鼠标来对文本内容进行交互性地 ...

  4. Linux下SHA256校验

    一.将Hash: SHA256文件和需要检验的文件放在同一个文件夹内 二.$sha256sum -c SHA265 文件 输出: 校验文件:ok

  5. require.context

    带表达式的 require 语句 如果你的 require参数含有表达式(expressions),会创建一个上下文(context),因为在编译时(compile time)并不清楚具体是哪一个模块 ...

  6. Hands-on ML and TF Chapter16 Reinforcement Learning

    Policy Granients import tensorflow as tf reset_graph() n_inputs = 4 n_hidden = 4 n_outputs = 1 learn ...

  7. Fastadmin 后台编辑,或者添加的时候,出现的问题

    1.情况如图:编辑的时候,这个关联id,默认查出来的是用户昵称,如果要显示用户名,该怎么修改,不要着急,听我慢慢道来 2.首先要找到 编辑页面,检查问题 3.完成

  8. 前端单点登录(SSO)实现方法(二级域名与主域名)

    1.单点登录介绍 单点登录 SSO 全称 Singn Sign On .SSO 是指在多个应用系统中,用户只需要登录一次用户系统,就可以访问其他互相信任的应用系统.例如:在网易官网登录账户,那么再进入 ...

  9. Groovy脚本基础全攻略

    1 背景 Groovy脚本基于Java且拓展了Java,所以从某种程度来说掌握Java是学习Groovy的前提,故本文适用于不熟悉Groovy却想快速得到Groovy核心基础干货的Java开发者(注意 ...

  10. C#产生随机验证码的代码

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...