异步获取线程执行结果,JDK中的Future、Netty中的Future和Promise对比

JDK中的Future和Netty中的Future、Promise的关系

三者源头追溯

        Netty中的Future与JDK中的Future同名,但是是两个不同的接口。Netty中的Future继承自JDK的Future,而Promise又对Netty中的Future进行了扩展。

  • JDK中的Future源自JUC并发包:

  • Netty中的Future源自Netty中的并发包:import io.netty.util.concurrent.Future; 并继承JUC中的Future。

  • Netty中的Promise继承自Netty中的Future,并且是一个接口,下面有一个实现类DefaultPromise<V>:

三者之间的区别和联系

  • jdk Future 只能同步等待任务结束(或成功、或失败)才能得到结果

  • netty Future 可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束

  • netty Promise 不仅有 netty Future 的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器

  • JDK和Netty中的Future并不是自己创建的,而是执行任务的线程执行结束后自己创建并且返回的。对于Future的创建权以及结果的设置均不是自己控制的,而是执行任务的线程控制的。Netty中的Promise可以提交者自己创建随后作为一个容器,供其他线程使用。

 代码演示

JDK中的Future

        代码编写:

        JDK中Future的获取依赖于线程池,首先创建线程池。

package com.example.code.netty.c4;import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;@Slf4j
public class TestJDKFuture {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService service = Executors.newFixedThreadPool(2);// future的理解,就是线程之间通信的工具,一个线程中获取另一个线程的结果,需要另一个线程主动填充log.info("task begin ...");Future<Integer> future = service.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {log.info("task is running...");Thread.sleep(1000);// future是被动获取结果的,需要执行任务的线程向future中填充返回结果log.info("task is end ...");return 20;}});log.info("等待结果...");log.info("获取任务执行结果:{}", future.get());}
}

        结果展示:

        通过lombok中的@Slf4j注解,打印执行过程相关信息:主要关注①执行线程名称,②任务执行是都异步,获取结果是否是阻塞、同步。执行顺序如下所示:

         上述图片中的②和③执行顺序不能倒置,②属于主线程顺序执行,然而③属于新创建的线程中执行,线程的创建以及启动本身需要耗费一定的时间。

Netty中的Future

        Netty中的Future的获取依赖于EventLoop,需要首先创建EventLoop,等价于JDK中的Future的获取的线程池的创建。

        Netty中的Future对于结果的获取可以采用同步,也可也采用异步的方式。并且在异步获取结果时可以使用get()、getNow()两种方式获取。

  • get():获取任务结果,阻塞等待。
  • getNow():获取任务结果,非阻塞,还未产生结果时返回null。
package com.example.code.netty.c4;import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;@Slf4j
public class TestNettyFuture {public static void main(String[] args) throws ExecutionException, InterruptedException {EventLoopGroup eventLoopGroup = new NioEventLoopGroup();EventLoop eventLoop = eventLoopGroup.next();Future<Integer> future = eventLoop.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {log.info("task is running...");Thread.sleep(1000);// future是被动获取结果的,需要执行任务的线程向future中填充返回结果log.info("task is end ...");return 70;}});log.info("等待结果...");// 同步方式获取任务执行结果
//        log.info("获取任务执行结果:{}", future.get());// 异步方式获取执行结果future.addListener(new GenericFutureListener<Future<? super Integer>>() {@Overridepublic void operationComplete(Future<? super Integer> future) throws Exception {// 异步获取执行结果既可以用future.get()阻塞方法,也可以用future.getNow()非阻塞方法。// 异步既然执行到了回调函数这一步,肯定已经能够获取到执行结果。log.info("获取任务执行结果:{}", future.getNow());}});}
}

        代码执行结果:【同步】

        代码执行结果:【异步】 

        同步方式下最终任务执行结果70的获取线程是当前main线程,而异步方式下最终执行结果70的获取是在nioEventLoopGroup中的某个线程也即任务线程本身中获取。 

Netty中的Promise

        Netty中的Promise继承自Netty中的Future,在继承Future相关功能的基础上,又实现了功能的增强。不仅可以在任务正确执行后设置执行结果,也可以在任务执行失败后设置执行结果。

  • setSuccess():设置成功结果。
  • setFailure():设置失败结果。

        代码编写:

package com.example.code.netty.c4;import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultPromise;
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ExecutionException;@Slf4j
public class TestNettyPromise {public static void main(String[] args) throws ExecutionException, InterruptedException {EventLoop eventLoop = new NioEventLoopGroup().next();// 主动创建promise,结果容器DefaultPromise<Integer> promise = new DefaultPromise<>(eventLoop);log.info("task begin ...");new Thread(()->{log.info("task is running...");// 任意一个线程执行计算,计算完毕后向promise中填充结果。try {
//                int i = 1 / 0;Thread.sleep(1000);promise.setSuccess(10);} catch (Exception e) {
//                e.printStackTrace();promise.setFailure(e);}log.info("task end ...");}).start();log.info("等待结果...");log.info("获取任务执行结果:{}", promise.get());}
}

        代码执行结果:【同步】,异步执行结果不再演示,同Netty中的Future效果所示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/841554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电商API接口(api商品数据)【电商商品实时数据采集API接口】

众多品牌选择电商API实时数据采集接口进行采购&#xff0c;主要是出于以下几个重要原因&#xff1a; 第一&#xff0c;高效便捷。比价工具通过自动化的方式获取价格信息&#xff0c;避免了繁琐的人工操作&#xff0c;大大节省了时间和精力。 第二&#xff0c;精准比较。API比价…

如何使用ssh将vscode 连接到服务器上,手把手指导

一、背景 我们在开发时&#xff0c;经常是window上安装一个vscode编辑器&#xff0c;去连接一个虚拟机上的linux&#xff0c;这里常用的是SSH协议&#xff0c;了解其中的操作非常必要。 二、SSH协议 SSH&#xff08;Secure Shell&#xff09;是一种安全协议&#xff0c;用于…

redis的基本命令

数据库相关操作 Redis默认 16 个数据库&#xff0c;默认使⽤第 0个 select 0 # 切换数据库 dbsize # 查看数据库⼤⼩ flushall # 清除全部库数据 flushdb # 清空当前库数据 key相关的操作 keys * # 查看所有的key exists key # 判断当前key 是否存在。 expire ke…

C#屏蔽基类成员

可以用与积累成员名称相同的成员来屏蔽 要让编译器知道你在故意屏蔽继承的成员&#xff0c;可以用new修饰符。否则程序可以成功编译&#xff0c;但是编译器会警告你隐藏了一个继承的成员 using System;class someClass {public string F1 "Someclass F1";public v…

React18+TypeScript搭建通用中后台项目实战04 封装常用工具函数

接口请求参数类型 修改 src/api/request.ts 核心代码&#xff1a; // GET 请求 // param url 请求地址 // param params 查询参数 // return 返回Promise对象&#xff0c;内部类型是泛型 function get<T>(url: string, params: object): Promise<T> {return req…

YOLOv10 | 手把手教你利用yolov10训练自己数据集(含环境搭建 + 参数解析 + 数据集查找 + 模型训练、推理、导出)

一、前言 本文内含YOLOv10网络结构图 各个创新模块手撕结构图 训练教程 推理教程 参数解析 环境搭建 数据集获取等一些有关YOLOv10的内容&#xff01; 目录 一、 前言 二、整体网络结构图 三、空间-通道分离下采样 3.1 SCDown介绍 3.2 C2fUIB介绍 3.3 PSA介绍 …

微服务下认证授权框架的探讨

前言 市面上关于认证授权的框架已经比较丰富了,大都是关于单体应用的认证授权,在分布式架构下,使用比较多的方案是--<应用网关>,网关里集中认证,将认证通过的请求再转发给代理的服务,这种中心化的方式并不适用于微服务,这里讨论另一种方案--<认证中心>,利用jwt去中…

【数据库基础-mysql详解之索引的魅力(N叉树)】

索引的魅力目录 &#x1f308;索引的概念&#x1f308;使用场景&#x1f308;索引的使用&#x1f31e;&#x1f31e;&#x1f31e;查看MySQL中的默认索引&#x1f31e;&#x1f31e;&#x1f31e;创建索引&#x1f31e;&#x1f31e;&#x1f31e;删除索引 站在索引背后的那个男…

sheng的学习笔记-docker部署Greenplum

目录 docker安装gp数据库 mac版本 搭建gp数据库 连接数据库 windows版本 搭建gp数据库 连接数据库 docker安装gp数据库 mac版本 搭建gp数据库 打开终端&#xff0c;输入代码&#xff0c;查看版本 ocker search greenplum docker pull projectairws/greenplum docker…

Virtual Box安装Ubuntu及设置

Virtual Box安装Ubuntu及设置 本文包含以下内容&#xff1a; 使用Virtual Box安装Ubuntu Desktop。设置虚拟机中的Ubuntu&#xff0c;使之可访问互联网并可通过SSH访问。 Ubuntu Desktop下载 从官网下载&#xff0c;地址为&#xff1a;Download Ubuntu Desktop | Ubuntu U…

HTTP交互导致ECONNABORTED的原因之一

背景&#xff1a; 本次记录的&#xff0c;是一次使用HTTP交互过程中遇到的问题&#xff0c;问题不大&#xff0c;就是给题目上这个报错补充一种可能的解决方案。 程序大致流程&#xff1a; 1. 设备向服务器A请求信息 2. 拿到回复记录下回复内容中的数据包下载地址等信息 3…

games 101 作业4

games 101 作业4 题目题解作业答案 题目 Bzier 曲线是一种用于计算机图形学的参数曲线。在本次作业中&#xff0c;你需要实 现 de Casteljau 算法来绘制由 4 个控制点表示的 Bzier 曲线 (当你正确实现该 算法时&#xff0c;你可以支持绘制由更多点来控制的 Bzier 曲线)。 你需…

IntelliJ IDEA实用插件:轻松生成时序图和类图

IntelliJ IDEA生成时序图、类图 一、SequenceDiagram1.1 插件安装1.2 插件设置1.3 生成时序图 二、PlantUML Integration2.1 插件安装2.2 插件设置2.3 生成类图 在软件建模课程的学习中&#xff0c;大家学习过多种图形表示方法&#xff0c;这些图形主要用于软件产品设计。在传统…

解释Python中的多线程和多进程编程

在Python中&#xff0c;多线程&#xff08;Multithreading&#xff09;和多进程&#xff08;Multiprocessing&#xff09;是两种常见的并发编程技术&#xff0c;用于同时执行多个任务。然而&#xff0c;由于Python的全局解释器锁&#xff08;GIL&#xff0c;Global Interpreter…

C++实现定长内存池

项目介绍 本项目实现的是一个高并发的内存池&#xff0c;它的原型是Google的一个开源项目tcmalloc&#xff0c;tcmalloc全称Thread-Caching Malloc&#xff0c;即线程缓存的malloc&#xff0c;实现了高效的多线程内存管理&#xff0c;用于替换系统的内存分配相关函数malloc和fr…

文件压缩下载

工具类FileUtil import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream;/*** 文件工具类** author: 张…

Java面向对象知识总结+思维导图

&#x1f516;面向对象 &#x1f4d6; Java作为面向对象的编程语言&#xff0c;我们首先必须要了解类和对象的概念&#xff0c;本章的所有内容和知识都是围绕类和对象展开的&#xff01; ▐ 思维导图1 ▐ 类和对象的概念 • 简单来说&#xff0c;类就是对具有相同特征的一类事…

一篇文章学明白go语言,你想知道是那篇文章吗?

一篇文章彻底搞明白go语言&#xff0c; 你没有看错就是一篇文章可以让你彻底搞明白go语言&#xff0c;这篇文章就是go语言官方的 The Go Programming Language Specification &#xff0c; 你把这个搞明白&#xff0c;go语言也就明白了。 文章地址https://go.dev/ref/spec 这篇…

spring自定义初始化的加载顺序

构造函数>PostConstruct > afterPropertiesSet > init-method

MySQL——表内容的CURD操作

MySQL表内容的CURD ​ 与表内容相关的操作共有四种类型&#xff1a;Create(创建)&#xff0c;Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete(删除)&#xff1b; 一、Create 1.1单行插入多行插入全列插入/指定列插入 #全列插入&#xff0c;忽略列属性&#xff…