NIO中的异步—ChannelFuture、CloseFuture以及异步提升在NIO中的应用

ChannelFuture

        客户端调用connect后返回值为ChannelFuture对象,我们可以利用ChannelFuture中的channel()方法获取到Channel对象。

        由于上述代为为客户端实现,若想启动客户端实现连接操作,必须编写服务端代码,实现如下:

package netty.simpleNetty.channel;import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;/*** 服务端配合ClientChannelFuture验证Channel关闭的异步以及回调函数实现*/
@Slf4j
public class ServerChannelFuture {public static void main(String[] args) throws InterruptedException {new ServerBootstrap().group(new NioEventLoopGroup(1), new NioEventLoopGroup(2)).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buffer = msg instanceof ByteBuf ? ((ByteBuf) msg) : null;if(buffer != null){byte[] bytes = new byte[16];ByteBuf len = buffer.readBytes(bytes, 0, buffer.readableBytes());log.info(new String(bytes));}}});}}).bind(8000).sync();}
}

        随后运行上述客户端代码,观察到日志输出如下:

         通过此输出日志发现借用channelFuture对象的channel方法获取的Channel对象并没有创建。

原因分析:connect方法是异步的,意味着不等待连接建立,方法执行就返回了。因此channelFuture对象中不能【立刻】获取到正确的Channel对象。

解决方法:

  • 使用sync方法让异步操作同步等待连接建立。
  • 使用回调方法,当connect连接建立后主动调用回调函数。

sync让异步操作同步

        获取到channelFuture对象后,调用sync()方法,同步等待连接的结束。sync阻塞住当前线程,直到Nio线程连接建立完毕 。先启动服务端再启动客户端日志输出如下:

         此时调用channelFuture.channle()方法获取到Channel,随后可以利用获取到的channel向服务端发送消息。

使用回调函数 

        调用获取的channelFuture对象的addListener()方法向其添加回调函数。

        可以将上述代码用Lambda表达式简化如下:

         服务端整体代码实现如下:

package netty.simpleNetty.channel;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;/*** 客户端关闭channel异步以及回调函数实现*/
@Slf4j
public class ClientChannelFuture {public static void main(String[] args) throws UnknownHostException, InterruptedException {ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup(2)).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {}}).connect(new InetSocketAddress(InetAddress.getLocalHost(), 8000));log.info("Before sync : {}",channelFuture.channel());
//        channelFuture.sync();
//        log.info("After sync : {}", channelFuture.channel());channelFuture.addListener((ChannelFutureListener)future -> {log.info("After listen : {}", future.channel());});
//        channelFuture.addListener(new ChannelFutureListener() {
//            @Override
//            public void operationComplete(ChannelFuture future) throws Exception {
//                log.info("After listen : {}", future.channel());
//            }
//        });}
}

CloseFuture

        上述操作探讨了调用connect方法建立连接后,根据chanelFuture获取到Channel对象的sync以及回调方法实现。在获取到Channel对象后,执行对应的writeAndFlush()方法发送消息后,需要及时关闭channel。

        channel关闭操作的实现有sync同步等待以及添加回调的实现方法:代码如下:

package netty.simpleNetty.channel;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Scanner;/*** Test CloseFuture的异步以及回调实现*/
@Slf4j
public class ClientCloseFuture {public static void main(String[] args) throws InterruptedException, UnknownHostException {Channel channel = new Bootstrap().group(new NioEventLoopGroup(2)).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));ch.pipeline().addLast(new StringEncoder());}}).connect(new InetSocketAddress(InetAddress.getLocalHost(), 8000)).sync().channel();log.info("channel : {}", channel);new Thread(()->{Scanner scanner = new Scanner(System.in);while (true){String line = scanner.nextLine();if("q".equals(line)){// channel的close也是一个异步操作,本线程不会执行close操作,而是交由一个其他线程执行close操作channel.close();break;}channel.writeAndFlush(line);}}).start();ChannelFuture closeFuture = channel.closeFuture();log.info("waiting close...");closeFuture.sync();log.info("closed...");channel.closeFuture().addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {log.info("closed...");}});//        channel.closeFuture().addListener((ChannelFutureListener) channelFuture1 ->{
//                    log.info("closed...");
//        });}
}

异步提升

        针对上述connect以及close操作,真正执行对应方法是在一个新的线程中执行的,而不是在调用connect的线程中执行连接操作。

        为什么不在一个线程中去执行建立连接、去执行关闭 channel【建立连接connet,关闭channel都是在EventLoopGroup中执行的。也即nio中执行的】,那样不是也可以吗?非要用这么复杂的异步方式:比如一个线程发起建立连接,另一个线程去真正建立连接。

        因为 netty 异步方式用了多线程、多线程就效率高。(理解错误的)

         netty中的异步指的是建立连接connet、读取数据read、关闭channel等不再一个线程中。而是由专门的线程(handler、EventLoop)负责执行专门的操作。

        思考下面的场景,4 个医生给人看病,每个病人花费 20 分钟,而且医生看病的过程中是以病人为单位的,一个病人看完了,才能看下一个病人。假设病人源源不断地来,可以计算一下 4 个医生一天工作 8 小时,处理的病人总数是:4 * 8 * 3 = 96。

经研究发现,看病可以细分为四个步骤,经拆分后每个步骤需要 5 分钟,如下

因此可以做如下优化,只有一开始,医生 2、3、4 分别要等待 5、10、15 分钟才能执行工作,但只要后续病人源源不断地来,他们就能够满负荷工作,并且处理病人的能力提高到了 4 * 8 * 12 效率几乎是原来的四倍。

  • 单线程没法异步提高效率,必须配合多线程、多核 cpu 才能发挥异步的优势

  • 异步并没有缩短响应时间,反而有所增加。【这里所说的响应时间的增加主要指的是不同子任务之间等待的耗时。

  • 合理进行任务拆分,也是利用异步的关键

 

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

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

相关文章

python中的randint如何使用

python中的randint用来生成随机数&#xff0c;在使用randint之前&#xff0c;需要调用random库。random.randint()是随机生成指定范围内的整数&#xff0c;其有两个参数&#xff0c;一个是范围上限&#xff0c;一个是范围下限。 具体用法如下&#xff1a; import random print…

USB3.2 摘录(四)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; 文章目录 系列文章目录8 协议层&#xff08;Protocol Layer&#xff09;8.8 三个参数地址信息&…

苍穹外卖项目DAY07

苍穹外卖项目Day07 1、缓存菜品 1.1、问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 1.2、实现思路 通过Redis来缓存菜品的数据&#xff0c;减少数据库查询操作 缓存逻辑分析&#xff…

未来视界,触手可及:揭秘数字透明屏的奇幻之旅

在这个日新月异的科技时代&#xff0c;每一项创新都如同星辰般璀璨&#xff0c;引领着我们向更加智能、更加梦幻的未来迈进。今天&#xff0c;就让我们一起揭开一项颠覆传统视觉体验的前沿科技——数字透明屏的神秘面纱&#xff0c;探索它如何将未来视界&#xff0c;化为触手可…

IDEA:如何在idea中设置自动导包

这里使用的是idea2020版本,但是不同版本操作不会有较大的差别. 在Editer中展开General之后,选中Auto Import,最后勾选中Add unambiguous imports on the fly.

微信视频号评论如何快速采集?三种高效实用的方法

本文将深入探讨如何高效地采集微信视频号评论&#xff0c;通过揭秘三种实用方法&#xff0c;助您迅速掌握这一营销利器。从自动化工具到智能策略&#xff0c;每一步都旨在提升您的市场分析效率&#xff0c;让您在竞争激烈的社交媒体领域中脱颖而出。 一、引言&#xff1a;为何…

探索顶级PDF水印API:PDFBlocks(2024年更新)

引言 在一个敏感信息常常面临风险的时代&#xff0c;能够轻松高效地保护文档的能力至关重要。PDF水印已成为企业和个人寻求保护其知识产权、确保文件保密性的基本工具。 PDFBlocks 文字水印 API是什么&#xff1f; PDFBlocks API 提供了一个强大的解决方案&#xff0c;用于在…

day06——前后端交互

一、计算属性 计算属性就是基于现有的数据推算出来的新属性&#xff0c;只要依赖的数据变化&#xff0c;新属性就会自动更新&#xff0c;而且计算属性多次调用的情况下只会计算一次&#xff0c;效率非常高 简化写法 const app new Vue({ el: #app, data: {}, methods: {//跟da…

记录一次生产jvm问题的排查

记录一次生产问题的排查 第一天晚上 现象 1、前援反馈页面有接口陆续出现请求超时 2、登录后台服务器top命令查看发现java进程发生高cpu占用情况 3、查看对应业务日志&#xff0c;报数据库连接等待超时-数据库连接池连接无空闲 对应处理 1、临时调大数据库连接池最大连接数限…

Chat App 项目之解析(三)

Chat App 项目介绍与解析&#xff08;一&#xff09;-CSDN博客文章浏览阅读76次。Chat App 是一个实时聊天应用程序&#xff0c;旨在为用户提供一个简单、直观的聊天平台。该应用程序不仅支持普通用户的注册和登录&#xff0c;还提供了管理员登录功能&#xff0c;以便管理员可以…

【三维重建汇总】NeRF和GS重建中,如何排除干扰物?(提升质量)

汇总最近NeRF与GS提升质量的论文 文章目录 前言一、NeRF On-the-go&#xff1a;利用不确定性落地真实世界&#xff08;CVPR24&#xff09;摘要1.DINOv2特征的不确定性预测2.NeRF中干扰物去除的不确定性3.优化4. Dilated Patch 扩大采样5.实验结果 二、Pixel-GS:像素感知的梯度密…

unity程序简易框架

1. 框架基本结构 2. 单例模式基类模块 2.1 BaseManager.cs using System.Collections; using System.Collections.Generic; using UnityEngine;public class BaseManager<T> where T:new() {private static T instance;public static T GetInstance(){if (instance == …

高防服务器配置要素

高防服务器配置通常包括硬件资源、网络资源、防护能力、弹性防护、清洗能力和业务支持等方面。下面将详细介绍高防服务器的配置要素&#xff0c;rak部落小编为您整理发布。 高防服务器是设计用来抵御各种网络攻击&#xff0c;特别是分布式拒绝服务(DDoS)攻击的服务器配置。这些…

伊朗通过 ChatGPT 试图影响美国大选, OpenAI 封禁多个账户|TodayAI

OpenAI 近日宣布&#xff0c;他们已经封禁了一系列与伊朗影响行动有关的 ChatGPT 账户&#xff0c;这些账户涉嫌利用该 AI 工具生成并传播与美国总统选举、以色列 – 哈马斯战争以及奥运会等相关的内容。 OpenAI 表示&#xff0c;这些账户与一个名为 “Storm-2035” 的秘密伊朗…

技术速递|Python in Visual Studio Code 2024年8月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展将于 2024 年 8 月发布&#xff01; 此版本包括以下公告&#xff1a; 使用 python-environment-tools 改进了 Python 发现源代码中显示的内联变量值对 Python 的 VS Code Native RE…

CentOS7下制作openssl1.1.1i RPM包并升级

OpenSSL最新漏洞 OpenSSL官方发布了拒绝服务漏洞风险通告&#xff0c;漏洞编号为CVE-2020-1971 漏洞详情 OpenSSL是一个开放源代码的软件库包&#xff0c;应用程序可以使用这个包来进行安全通信&#xff0c;避免窃听&#xff0c;同时确认另一端连接者的身份。这个包广泛被应…

LangChain深度解析:模型调用的艺术与实践

Model I/O 概述 LangChain的模型是框架中的核心&#xff0c;基于语言模型构建&#xff0c;用于开发LangChain应用。通过API调用大模型来解决问题是LangChain应用开发的关键过程。 可以把对模型的使用过程拆解成三块: 输入提示(Format)、调用模型(Predict)、输出解析(Parse) 1.…

【Kubernetes中如何对etcd进行备份和还原】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

开放式耳机哪种好用?开放式种草测评!

现在很多人都很喜欢用开放式耳机了&#xff0c;因为这种耳机非常的舒服&#xff0c;而且不会压迫我们的耳道&#xff0c;从而给到我们更健康的体验&#xff0c;但是现在开放式耳机的品牌越来越多&#xff0c;我们也越来越难选择&#xff0c;所以我们应该怎么样才能选到一款适合…

(七)Activiti-modeler中文支持

1、修改app.js&#xff0c;51行 注意第3步&#xff0c;之前已经访问过&#xff0c;缓存到cookie了&#xff0c;这里要么注释该方法&#xff0c;要么去浏览器手动删除对应cookie才能使用下面的zh-CN.json 2、i18n\en.json中添加zh-CN.json &#xff08;以下代码片断为网上获得…