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. 如何使用C#编写低代码应用插件

    本文由葡萄城技术团队发布.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 作为当今快速发展的技术之一,低代码平台为开发人员提供了更高效.更简便的工具和 ...

  2. 实例讲解C++连接各种数据库,包含SQL Server、MySQL、Oracle、ACCESS、SQLite 和 PostgreSQL、MongoDB 数据库

    C++ 是一种通用的编程语言,可以使用不同的库和驱动程序来连接各种数据库.以下是一些示例代码,演示如何使用 C++ 连接 SQL Server.MySQL.Oracle.ACCESS.SQLite 和 ...

  3. Flutter搭建

    目录 下载 Flutter SDK 配置 Flutter 环境变量及镜像 检查开发环境 参考 下载 Flutter SDK flutter官网下载:https://flutter.io/sdk-arc ...

  4. 3C智能移动周边产品龙头企业如何集成企业内部所有异构系统数据

    全面并自动集成品胜集团全域业务系统中的各类业务数据:结构化.标准化.自动化集团全部异构系统数据,提升全公司整体项目管理水平:梳理与简化跨部门.跨系统流程,清晰定义流程节点及业务边界,打通部门间信息流通 ...

  5. preparedStatement.setString()方法

    PreparedStatement作用:PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程. 1.预编译sql语句,效率高 2.安全,避免sql注入 3 ...

  6. classpath 和 classpath* 的区别

    classpath 和 classpath* 的区别 classpath 和 classpath* 是两种不同的类路径搜索模式,它们在寻找资源文件时有所不同: classpath:classpath ...

  7. Java八股面试整理(3)

    21.说一说hashCode()和equals()的关系 hashCode()用于获取哈希码(散列码),eauqls()用于比较两个对象是否相等,它们应遵守如下规定: 如果两个对象相等,则它们必须有相 ...

  8. 实例讲解Python 解析JSON实现主机管理

    本文分享自华为云社区<Python 解析JSON实现主机管理>,作者: LyShark. JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易 ...

  9. idea用不了 idea.bat文件闪退

    由于idea的智能,在破解之后会留下一些问题,根据网上搜出来的解决办法. 1.C:\Users\dell\AppData\Roaming\JetBrains\IntelliJIdea2022.2 在这 ...

  10. Chrome扩展的核心:manifest 文件(中)

    大家好,我是 dom 哥.我正在写关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星 . 在上一篇中已经完成了 Chrome 扩展的雏形,本篇接着介绍 manifest 中的可选字段,完 ...