Netty篇(核心组件 - Channel)

目录

一、简介

二、ChannelFuture

三、CloseFuture

四、💡 异步提升的是什么


一、简介

channel 的主要作用

  • close() 可以用来关闭 channel
  • closeFuture() 用来处理 channel 的关闭
    • sync 方法作用是同步等待 channel 关闭
    • 而 addListener 方法是异步等待 channel 关闭
  • pipeline() 方法添加处理器
  • write() 方法将数据写入
  • writeAndFlush() 方法将数据写入并刷出

二、ChannelFuture

这时刚才的客户端代码

    public static void test01(){try {new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder());}}).connect("127.0.0.1", 8080).sync().channel().writeAndFlush(new Date() + ": hello world!");} catch (InterruptedException e) {throw new RuntimeException(e);}}

现在把它拆开来看

    public static void test02(){ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder());}}).connect("127.0.0.1", 8080); // 1try {channelFuture.sync().channel().writeAndFlush(new Date() + ": hello world!");} catch (InterruptedException e) {throw new RuntimeException(e);}}
  • 1 处返回的是 ChannelFuture 对象,它的作用是利用 channel() 方法来获取 Channel 对象

注意

connect 方法是异步的,意味着不等连接建立,方法执行就返回了。

因此 channelFuture 对象中不能【立刻】获得到正确的 Channel 对象

实验如下:

    public static void test03(){ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder());}}).connect("127.0.0.1", 8080);System.out.println(channelFuture.channel()); // 1try {channelFuture.sync(); // 2} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(channelFuture.channel()); // 3}
  • 执行到 1 时,连接未建立,打印 [id: 0x2e1884dd]
  • 执行到 2 时,sync 方法是同步等待连接建立完成
  • 执行到 3 时,连接肯定建立了,打印 [id: 0xd3e8b042, L:/127.0.0.1:62083 - R:/127.0.0.1:8080]

除了用 sync 方法可以让异步操作同步以外,还可以使用回调的方式:

    public static void test04() {ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder());}}).connect("127.0.0.1", 8080);System.out.println(channelFuture.channel()); // 1channelFuture.addListener((ChannelFutureListener) future -> {System.out.println(future.channel()); // 2});}
  • 执行到 1 时,连接未建立,打印 [id: 0xe72025cf]
  • ChannelFutureListener 会在连接建立时被调用(其中 operationComplete 方法),因此执行到 2 时,连

接肯定建立了,打印 [id: 0xe72025cf, L:/127.0.0.1:62263 - R:/127.0.0.1:8080]

三、CloseFuture

@Slf4j
public class CloseFutureClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup group new NioEventLoopGroup();ChannelFuture channelFuture = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Override // 在连接建立后被调用protected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));ch.pipeline().addLast(new StringEncoder());}}).connect(new InetSocketAddress("localhost", 8080));Channel channel = channelFuture.sync().channel();log.debug("{}", channel);new Thread(()->{Scanner scanner = new Scanner(System.in);while (true) {String line = scanner.nextLine();if ("q".equals(line)) {channel.close(); // close 异步操作 1s 之后
//                    log.debug("处理关闭之后的操作"); // 不能在这里善后break;}channel.writeAndFlush(line);}}, "input").start();// 获取 CloseFuture 对象, 1) 同步处理关闭, 2) 异步处理关闭ChannelFuture closeFuture = channel.closeFuture();/*log.debug("waiting close...");closeFuture.sync();log.debug("处理关闭之后的操作");*/closeFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {log.debug("处理关闭之后的操作");group.shutdownGracefully();}});}
}

四、💡 异步提升的是什么

  • 有些同学看到这里会有疑问:为什么不在一个线程中去执行建立连接、去执行关闭 channel,那样不是也可以

吗?非要用这么复杂的异步方式:比如一个线程发起建立连接,另一个线程去真正建立连接

  • 还有同学会笼统地回答,因为 netty 异步方式用了多线程、多线程就效率高。

其实这些认识都比较片面,多线程和异步所提升的效率并不是所认为的

思考下面的场景,4 个医生给人看病,每个病人花费 20 分钟,而且医生看病的过程中是以病人为单位的,一个病

人看完了,才能看下一个病人。假设病人源源不断地来,可以计算一下 4 个医生一天工作 8 小时,处理的病人总

数是:4 * 8 * 3 = 96

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

因此可以做如下优化,只有一开始,医生 2、3、4 分别要等待 5、10、15 分钟才能执行工作,但只要后续病人源

源不断地来,他们就能够满负荷工作,并且处理病人的能力提高到了 4 * 8 * 12 效率几乎是原来的四倍

要点

  • 单线程没法异步提高效率,必须配合多线程、多核 cpu 才能发挥异步的优势
  • 异步并没有缩短响应时间,反而有所增加
  • 合理进行任务拆分,也是利用异步的关键

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript void 运算符

void定义&#xff1a; void 运算符对给定的表达式进行求值&#xff0c;然后返回undefined。void是一个一元运算符&#xff0c;接受单个操作数&#xff0c;可以是任何类型&#xff0c;返回一个 undefined。 void语法&#xff1a; void 在表达式的左边&#xff0c;void 右边的…

Vue+Springboot 前后端分离的项目如何部署?

本文转载自&#xff1a;https://fangcaicoding.cn/course/11/58 大家好&#xff01;我是方才&#xff0c;目前是8人后端研发团队的负责人&#xff0c;拥有6年后端经验&3年团队管理经验&#xff0c;截止目前面试过近200位候选人&#xff0c;主导过单表上10亿、累计上100亿数…

sls日志服务采集json格式日志

springboot统计的json数据 1. 配置 Logback 输出 JSON 格式日志1.1添加依赖&#xff1a;1.2配置 Logback 输出日志&#xff1a; 2. 使用 LinkedHashMap 日志数据3. 将日志推送到 SLS4. 在阿里云 SLS 中查看日志5.补充&#xff1a;关于 JSON 格式输出5.补充&#xff1a;关于 JSO…

Python | Leetcode Python题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; class Solution:def convertBST(self, root: TreeNode) -> TreeNode:def getSuccessor(node: TreeNode) -> TreeNode:succ node.rightwhile succ.left and succ.left ! node:succ succ.leftreturn succtotal 0node rootwhile nod…

天命人开店日记之选址考察(上)

本次开店的品类是老年用品&#xff0c;前期与合作伙伴交流&#xff0c;按照新的线上与线下结合方式销售老年代步车和智能电动轮椅&#xff0c;线上占据70%销量&#xff0c;线下占据30%。线下门店可作为一个体验中心&#xff0c;对于本区域内的用户可以到线下门店体验&#xff0…

万字长文读懂RAG

目录 RAG的整体架构设计 一、概览 1-Overview 2-Indexing 3-Retrival 4-Generation 二、优化元素提问 5-Multi Query多查询策略 6-RAG-Fusion多查询结果融合策略 7-Decomposition问题分解策略 Answer recursively Answer individually 8-Step Back问答回退策略 9…

MySQL系列:一句SQL,MySQL是怎么工作的?

对于MySQL而言&#xff0c;其实分为客户端与服务端。 服务端&#xff0c;就是MySQL应用&#xff0c;当我们使用net start mysql命令启动的服务&#xff0c;其实就是启动了MySQL的服务端。客户端&#xff0c;负责发送请求到服务端并从服务端获取数据&#xff0c;客户端可以有多种…

【Mysql NDB Cluster 集群(CentOS 7)安装笔记一】

Mysql NDB Cluster 集群(CentOS 7)安装笔记 NDB集群核心概念 NDBCLUSTER(也称为NDB)是一个内存存储引擎,提供高可用性和数据保存功能。 NDBCLUSTER存储引擎可以配置一系列故障转移和负载平衡选项,但从集群级别的存储引擎开始是最容易的。NDB集群的NDB存储引擎包含一整套…

使用VS Code时如何切换Python版本?VS Code中如何在Python3与Python2之间自由切换?

1. 使用VS Code时如何切换Python版本&#xff1f;VS Code中如何在Python3与Python2之间自由切换&#xff1f; 2. 准备 2.1. 已添加Python2与Python3的安装目录到环境变量的Path所对应的值里 2.2. 已安装VSCode的Python插件 没安装的话&#xff0c;用VSCode打开Py文件就会提示让…

爱回收根关键字获取对应品牌的ID API 返回值深入解析

在数字化时代&#xff0c;二手商品交易市场日益繁荣&#xff0c;其中爱回收作为一个重要的平台&#xff0c;提供了一个便捷的接口&#xff0c;使得开发者能够通过API获取对应品牌的ID。本文将详细介绍如何使用爱回收的API&#xff0c;通过根关键字来获取品牌ID&#xff0c;并提…

给自己域名生成tls证书并在服务器进行配置

背景 自己搭建的服务器&#xff0c;使用https访问时会报不安全&#xff0c;给人一种不靠谱的赶脚&#xff0c;于是乎&#xff0c;决定使用个免费的方式来配置个证书解决这个问题 解决 首先需要有自己的公网域名&#xff0c;我的是某里云购买的,如何购买域名这里不聊 需要一…

java反序列化学习之CommonCollections3利用链的学习

一、前言 在前文中&#xff0c;我们学习了Java的类加载过程&#xff0c;类加载器以及Java中加载字节码的一些方法&#xff0c;其中介绍了TemplatesImpl&#xff0c;TemplatesImpl是一个可以加载字节码的类&#xff0c;通过调用其newTransformer()方法&#xff0c;即可执行这段字…

钨酸铵溶液净化除钾钠杂质

钨酸铵溶液的主要用途包括制造三氧化钨、蓝色氧化钨、偏钨酸铵及其他钨化合物&#xff0c;以及作为石油化工行业的添加剂‌‌ 制造其他钨化合物&#xff1a; 钨酸铵溶液可以用于制造三氧化钨或蓝色氧化钨&#xff0c;这些化合物进一步用于生产金属钨粉。金属钨粉是制造钨条、钨…

线程安全的单例模式

单列模式是校考中最常考的设计模式之一 啥是设计模式&#xff1f; 设计模式就好比好比向其中的“棋谱”&#xff0c;红方当头炮&#xff0c;黑方马来跳。针对红方的一些走法黑方有一些固定的套路。按照套路来走局势就不会吃亏。 软件开发中有很对常见的“问题场景‘&#xff1a…

【云岚到家】-day09-1-项目迁移6-秒杀抢购介绍

【云岚到家】-day09-1-项目迁移6-秒杀抢购介绍 1 购物车1.1 交互流程1.2 Redis数据结构1.3 表设计1.4 定时同步购物车 2 签到活动2.1 需求分析2.2 系统设计2.2.1 表设计2.2.2 接口设计2.2.3 如何计算连续签到天数2.2.4 如何获取匹配签到奖励规则2.2.5 签到代码 3 秒杀抢购介绍1…

探索LINQ在C#中的应用:从基本查询到数据联接

LINQ&#xff08;语言集成查询&#xff09;是微软为.NET框架开发的一种强大功能&#xff0c;于2007年作为C# 3.0和Visual Basic .NET 9.0的一部分引入。LINQ的诞生旨在提供一种一致且直观的方式来查询和操作数据&#xff0c;无论数据来源是内存中的集合、数据库还是XML文档。 …

FileLink如何帮助医疗行业实现安全且高效的跨网文件交换

在当今数字化时代&#xff0c;医疗行业在快速发展的同时&#xff0c;也面临着数据安全和信息流转效率的双重挑战。患者的健康记录、影像数据、检查报告等大量敏感信息需要在不同医院、诊所、实验室和保险公司之间高效、迅速地传递。然而&#xff0c;传统的邮件、传真和纸质文件…

windows工具 -- 一个定时播放音乐并延迟锁屏的bat脚本(专注模式) 每隔45分钟电脑自动锁屏

目的 由于静脉曲张比较难受, 不能长时间坐着, 需要有一个强迫休息的功能: 工作45分钟45分钟到了, 自动播放音乐, 并提示30s后进行锁屏 创建bat脚本 创建一个 .txt 文本文件, 然后修改后缀名为 .bat 右键记事本打开, 复制以下代码保存 echo off :: 等待45分钟 TIMEOUT /T 2700…

opencv_相关的问题

Debug模型下运行&#xff0c;在命令行窗口会有一些error相关的log信息。 通过调整log的等级&#xff0c;屏蔽掉INFO的log信息 #include <opencv2/core/utils/logger.hpp>cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_ERROR);

深度学习-44-大模型预训练的数据预处理及大模型的分类

文章目录 1 大模型的分类1.1 按任务类型分类1.1.1 生成式模型1.1.2 判别式模型1.1.3 混合模型1.2 按数据模态分类1.2.1 单模态模型1.2.2 多模态模型1.3 按训练方法分类1.3.1 预训练模型1.3.2 从零训练模型1.3.3 迁移学习模型1.4 按应用领域分类1.4.1 自然语言处理模型1.4.2 计算…