JDK  实现

public class FutureTest { 

    public static void main(String[] args) throws Exception {
ExecutorService es = Executors.newFixedThreadPool(10);
Future<Integer> f = es.submit(() ->{
Thread.sleep(5000);
// 结果
return 100;
}); Integer result = f.get();
System.out.println(result); // 也可以轮询等结束
// while (f.isDone()) {
// System.out.println(result);
// }
} }

虽然这些方法提供了异步执行任务的能力,但是对于结果的获取却还是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。
阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的CPU资源,而且也不能及时的得到计算结果。
Java的一些框架,
Netty,自己扩展了Java的 Future 接口,提供了 addListener 等多个扩展方法。
Google的guava也提供了通用的扩展Future:ListenableFuture 、 SettableFuture 以及辅助类 Futures 等,方便异步编程。
Java 在JDK1.8 这个版本中增加了一个能力更强的Future类:CompletableFuture 。它提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果。下面来看看这几种方式。

Netty-Future

引入Maven依赖:

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.50.Final</version>
</dependency>

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
package com.vipsoft;

import cn.hutool.core.date.DateUtil;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener; import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; public class FutureTest { public static void main(String[] args) throws InterruptedException {
EventExecutorGroup group = new DefaultEventExecutorGroup(4);
System.out.println("开始:" + DateUtil.now()); Future<Integer> f = group.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("开始耗时计算:" + DateUtil.now());
Thread.sleep(5000);
System.out.println("结束耗时计算:" + DateUtil.now());
int a = 0;
int b = 1;
int c = b / a;
return 100;
}
}); //通过监听,待线程结束后,自动触发,避免了主线程 的阻塞和等待
f.addListener(new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> objectFuture) throws Exception {
System.out.println("计算结果:" + objectFuture.get());
}
}); System.out.println("结束:" + DateUtil.now());
// 不让守护线程退出
new CountDownLatch(1).await();
} }

在Listener添加成功之后,会立即检查状态,如果任务已经完成立刻进行回调,通过监听,待线程结束后,自动触发,避免了主线程 的阻塞和等待

Guava-Future

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
package com.vipsoft;

import cn.hutool.core.date.DateUtil;
import com.google.common.util.concurrent.*; import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class FutureTest { public static void main(String[] args) throws InterruptedException {
System.out.println("开始:" + DateUtil.now()); ExecutorService executorService = Executors.newFixedThreadPool(10);
ListeningExecutorService service = MoreExecutors.listeningDecorator(executorService);
ListenableFuture<Integer> future = service.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("开始耗时计算:" + DateUtil.now());
Thread.sleep(5000);
System.out.println("结束耗时计算:" + DateUtil.now());
return 100;
}
}); //增加回调函数,一般用于不在乎执行结果的地方
future.addListener(new Runnable() {
@Override
public void run() {
System.out.println("调用成功--不关心结果");
}
}, executorService); //通过addCallback 获得结果
Futures.addCallback(future, new FutureCallback<Integer>() {
@Override
public void onSuccess(@Nullable Integer result) {
System.out.println("成功,计算结果:" + result);
} @Override
public void onFailure(Throwable t) {
System.out.println("失败");
}
}, executorService); System.out.println("结束:" + DateUtil.now());
new CountDownLatch(1).await();
}
}

CompletableFuture 使用

package com.vipsoft;

import cn.hutool.core.date.DateUtil;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch; public class FutureTest { public static void main(String[] args) throws InterruptedException {
System.out.println("开始:" + DateUtil.now());
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("开始耗时计算:" + DateUtil.now());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束耗时计算:" + DateUtil.now());
return 100;
});
//使用 thenCompose 或者 thenComposeAsync 等方法可以实现回调的回调,且写出来的方法易于维护。
completableFuture = completableFuture.thenCompose(i -> {
return CompletableFuture.supplyAsync(() -> {
System.out.println("在回调的回调中执行耗时操作...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return i + 200;
});
});
completableFuture.whenComplete((result, e) -> {
System.out.println("回调结果:" + result);
}); System.out.println("结束:" + DateUtil.now());
new CountDownLatch(1).await();
}
}

JDK1.8 已经提供了一种更为高级的回调方式:CompletableFuture,不需要引入任何第三方的依赖,为Future模式增加回调功能就不需要阻塞等待结果的返回并且不需要消耗无谓的CPU资源去轮询处理状态,JDK8之前使用Netty或者Guava提供的工具类,JDK8之后则可以使用自带的 CompletableFuture 类。Future 有两种模式:将来式和回调式。而回调式会出现回调地狱的问题,由此衍生出了 Promise 模式来解决这个问题。这才是 Future 模式和 Promise 模式的相关性。

多种方式实现 Future 回调返回结果的更多相关文章

  1. PDO多种方式取得查询结果

    PDO多种方式取得查询结果 01 December 2009 1:26 Tuesday by Sjolzy PDO最大的特点之一是它的灵活性,本节将介绍如何取得查询结果,包括: 数组(数值或关联数组) ...

  2. 11月18日内容总结——同步、异步与阻塞、非阻塞的概念、创建进程的多种方式及multiprocessing模块、进程间的数据隔离和IPC机制(队列)、生产者消费者模型、守护进程、僵尸进程、孤儿进程和多进程错乱问题

    目录 一.同步与异步 同步 异步 二.阻塞与非阻塞 阻塞 非阻塞 三.综合使用 1.同步阻塞: 2.同步非阻塞: 3.异步阻塞: 4.异步非阻塞: 四.创建进程的多种方式 进程的创建 multipro ...

  3. Spring学习总结(一)——Spring实现IoC的多种方式

    控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法.没有IoC的程序中我们使用面向对象编程对象的创 ...

  4. sql语句分页多种方式ROW_NUMBER()OVER

    sql语句分页多种方式ROW_NUMBER()OVER 摘自: http://www.cnblogs.com/CodingArt/articles/1692468.html 方式一 select to ...

  5. JavaScript中判断为整数的多种方式

    之前记录过JavaScript中判断为数字类型的多种方式,这篇看看如何判断为整数类型(Integer). JavaScript中不区分整数和浮点数,所有数字内部都采用64位浮点格式表示,和Java的d ...

  6. 使用多种方式实现遍历HashMap

    今天讲解的主要是使用多种方式来实现遍历HashMap取出Key和value,首先在java中如果想让一个集合能够用for增强来实现迭代,那么此接口或类必须实现Iterable接口,那么Iterable ...

  7. Jquery Validate 表单验证的多种方式

    ASP.NET MVC Jquery Validate 表单验证的多种方式 在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体 ...

  8. Spring实现Ioc的多种方式--控制反转、依赖注入、xml配置的方式实现IoC、对象作用域

    Spring实现Ioc的多种方式 一.IoC基础 1.1.概念: 1.IoC 控制反转(Inversion of Control) IoC是一种设计思想. 2.DI 依赖注入 依赖注入是实现IoC的一 ...

  9. 在 ASP.NET 网页中不经过回发而以编程方式实现客户端回调

    在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作.此时将重新创建页及其控件,并在服务器上运行页代码,且新版本的页被呈现到浏览器.但是,在有些情况下,需要从客户 ...

  10. ASP.NET Core默认注入方式下如何注入多个实现(多种方式) - sky 胡萝卜星星 - CSDN博客

    原文:ASP.NET Core默认注入方式下如何注入多个实现(多种方式) - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.c ...

随机推荐

  1. 关于一类最优解存在长度为 $k$ 的循环节的问题

    灵感来源 问题形式:给定长度为 \(n\) 的序列,要求选出一些位置,使这些位置满足限制条件 \(T\),其中 \(T\) 可以表述为一个长度为 \(k\) 的环满足条件 \(T'\),选出第 \(i ...

  2. python,opencv-python人脸识别,并且发邮件对镜头前未知人员进行报警

    我们在任意一个硬盘的根目录下创建一个Code-project文件夹 在该文件夹下分别创建C-project和Python-project文件夹 在Python-project文件夹下创建face re ...

  3. js实现在报表参数界面获取body中控件的值

    要在报表参数界面获取body中控件的值,你可以使用JavaScript来实现.下面是一个详细的介绍: 1. DOM(文档对象模型): - DOM是用于操作HTML文档的API,它允许你通过JavaSc ...

  4. MacOS|matplotlib 无法显示中文 解决办法

    matplotlib 无法显示中文 解决办法 画图时,中文无法正常显示,如图 下载字体 点击这里获取字体 提取码: wnby 查看字体路径 在 python 环境中执行以下指令 import matp ...

  5. [AGC031E] Snuke the Phantom Thief

    Problem Statement A museum exhibits $N$ jewels, Jewel $1, 2, ..., N$. The coordinates of Jewel $i$ a ...

  6. CH395实现主动ping对端功能(代码及说明)

    目录 1.PING原理 1.1简介 1.2协议 1.3通信流程 2.代码解释 3.工程链接 PING原理 1.简介 PING是基于ICMP(Internet Control Message Proto ...

  7. 为什么要重写equals()?

    为什么要重写equals()? Equals和 == 的区别: ==:是个运算符, 判断是否相等,基本数据类型进行判断 也可判断两个对象相等,比较两个对象的哈希码值 Equals:是个Object类的 ...

  8. 生产升级JDK 17 必读手册

    原文点这里,查看更多优质文章 DK 17 在 2021 年 9 月 14 号正式发布了!根据发布的规划,这次发布的 JDK 17 是一个长期维护的版本(LTS). Java 17 提供了数千个性能.稳 ...

  9. OpenEuler22.03安装PostgreSQL15.5并配置一主二从

    环境准备 序号 IP 标识(hostname) CPU/内存配置 系统盘 数据盘 1 192.168.8.190 pg01 8C+16G 80G 500G 2 192.168.8.191 pg02 8 ...

  10. ElasticSearch之cat pending tasks API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/pending_tasks?v=true&pretty" --cacert ...