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. asp.net大文件传输断点续传源码

    HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...

  2. LibreOffice/Calc:带条件判断的求和

    本文适用于LibreOffice Calc 5.1.6.2 + Ubuntu 16.04,熊猫帮帮主@cnblogs 2018/3/7 以下图为例,假设要根据C列对D列中被选中单元进行求和,即对D列中 ...

  3. 交换机配置——跨交换机划分VLAN配置

    一.实验要求:实现跨交换地划分vlan的配置任务,使同一vlan下的主机能相互通讯 二.拓扑图如下; 三.具体实验步骤: S1交换机配置: S1>enable  --进入特权模式S1#confi ...

  4. 【CUDA 基础】4.2 内存管理

    title: [CUDA 基础]4.2 内存管理 categories: - CUDA - Freshman tags: - CUDA内存管理 - CUDA内存分配和释放 - CUDA内存传输 - 固 ...

  5. Codeforces 1167 F Scalar Queries 计算贡献+树状数组

    题意 给一个数列\(a\),定义\(f(l,r)\)为\(b_1, b_2, \dots, b_{r - l + 1}\),\(b_i = a_{l - 1 + i}\),将\(b\)排序,\(f(l ...

  6. Navicat Premium12远程连接MySQL数据库

    https://blog.csdn.net/dengjin20104042056/article/details/95091506 方法二: step1: 修改表user mysql> use ...

  7. Android中定义广播监听,其他页面发送

    private LocalBroadcastManager broadcastManager; /** * 注册广播接收器 */ private void receiveAdDownload() { ...

  8. (四)C语言之函数

  9. android 9.0以上charles https抓包

    以前安装证书的方式无效了,必须将下载的证书复制到/system/etc/security/cacerts/目录, 步骤: 1.现在手机上安装好 chls.pro/ssl下载得到一个 charles-p ...

  10. javascript之DOM总结

    DOM简介    全称Document Object Model,即文档对象模型.DOM描绘了一个层次化的树,允许开发人员添加.删除.修改页面的某一部分.    浏览器在解析HTML页面标记的时候,其 ...