【Netty】nio阻塞非阻塞Selector

阻塞VS非阻塞

阻塞
  • 阻塞模式下,相关方法都会导致线程暂停。

    • ServerSocketChannel.accept() 会在没有建立连接的时候让线程暂停

    • SocketChannel.read()会在没有数据的时候让线程暂停。

    • 阻塞的表现就是线程暂停了,暂停期间不会占用CPU,但线程相当于闲置。

  • 单线程下,阻塞方法之间相互影响,几乎不能正常工作,需要多线程支持。

  • 但多线程下又有新问题。

    • 32 位 jvm 一个线程 320k,64 位 jvm 一个线程 1024k,如果连接数过多,必然导致 OOM,并且线程太多,反而会因为频繁上下文切换导致性能降低

    • 可以采用线程池技术来减少线程数和线程上下文切换,但治标不治本,如果有很多连接建立,但长时间 inactive,会阻塞线程池中所有线程,因此不适合长连接,只适合短连接

服务器端

这个代码只能每次在连接到时候读取一次连接事件,进行遍历,其余事件阻塞,即使有其他的读写事件也没有反回应。

public class TestSocketChannel {
    public static void main(String[] args) throws IOException {
        //开启服务
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //ban
        ssc.bind(new InetSocketAddress(8080));
        List<SocketChannel> channels = new ArrayList<>();
        while (true) {
            //等待建立连接
            SocketChannel sc = ssc.accept();
            channels.add(sc);
            Iterator<SocketChannel> iterator = channels.iterator();
​
            while (iterator.hasNext()) {
​
                SocketChannel channel = iterator.next();
                ByteBuffer buffer = ByteBuffer.allocate(10);
                //读取数据
                int len = channel.read(buffer);
                ByteBufferUtil.debugAll(buffer);
                buffer.clear();
                log.debug("after read...{}", channel);  
            }
​
        }
    }
}

客户端

public class SocketChannelClient {
    public static void main(String[] args) throws IOException {
        SocketChannel sc = SocketChannel.open();
        sc.connect(new InetSocketAddress("localhost", 8080));
        System.out.println("waiting...");
    }
}

非阻塞
  • 非阻塞模式下,相关的方法都不会让线程暂停

    • 在ServerSocketChannel.accept()在没有建立连接时,会返回null.

    • SocketChannel.read在没有数据可读时返回0,但线程不必阻塞,可以执行其他SocketChannel的read或者ServerSocketChannel.accept

    • 写数据的时候,知识等待数据写入channel即可,无需等Channel通过网络把数据发出去。

  • 非阻塞模式下,即使没有连接建立和可读数据,线程任然在不断运行,拜拜浪费CPU

  • 数据复制过程中,线程实际还是阻塞的。(AIO改进的地方)

服务端代码

package com.aqiuo.socketchannel;
​
import com.aqiuo.buffer.ByteBufferUtil;
import lombok.extern.slf4j.Slf4j;
​
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@Slf4j
public class TestSocketChannel {
    public static void main(String[] args) throws IOException {
        //开启服务
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //绑定端口
        ssc.bind(new InetSocketAddress(8080));
        ssc.configureBlocking(false); //非阻塞模式
        //连接的集合
        List<SocketChannel> channels = new ArrayList<>();
        while (true) {
            //等待建立连接非阻塞,线程还好继续向下运行,没有连接返回null
            SocketChannel sc = ssc.accept();
            if(sc!=null){
                log.info("connected...{}",sc);
                sc.configureBlocking(false);//非阻塞模式
                channels.add(sc);
            }
            Iterator<SocketChannel> iterator = channels.iterator();
            while (iterator.hasNext()) {
​
                SocketChannel channel = iterator.next();
                ByteBuffer buffer = ByteBuffer.allocate(10);
                //非阻塞读取数据
                //接受客户端发送的数据。没有读到数据返回0
                int len = channel.read(buffer);
                if(len>0){
                    buffer.flip();
                    ByteBufferUtil.debugAll(buffer);
                    buffer.clear();
                    log.info("after read...{}",channel);
                }
​
            }
​
        }
    }
}
 
多路复用

单线程可以搭配Selector完成对多个channel可读可写事件的监控,称之为多路复用

  • 多路复用仅仅针对网络IO,普通文件IO无法利用多路复用。

  • 如果不用Selector的非阻塞模式,线程大部分事件都在做无用功,而Selector能够保证。

    • 有连接事件时采去连接

    • 有可读事件才去读取。

    • 有可写事件才去写入。

      • 限于网络传输能力,Channel 未必时时可写,一旦 Channel 可写,会触发 Selector 的可写事件

Selector

创建
Selector selector = Selector.open();
绑定 Channel 事件

也称之为注册事件,绑定的事件 selector 才会关心

channel.configureBlocking(false);
SelectionKey key = channel.register(selector, 绑定事件);
  • channel 必须工作在非阻塞模式

  • FileChannel 没有非阻塞模式,因此不能配合 selector 一起使用

  • 绑定的事件类型可以有

    • connect - 客户端连接成功时触发

    • accept - 服务器端成功接受连接时触发

    • read - 数据可读入时触发,有因为接收能力弱,数据暂不能读入的情况

    • write - 数据可写出时触发,有因为发送能力弱,数据暂不能写出的情况

监听 Channel 事件

可以通过下面三种方法来监听是否有事件发生,方法的返回值代表有多少 channel 发生了事件

方法1,阻塞直到绑定事件发生

int count = selector.select();

方法2,阻塞直到绑定事件发生,或是超时(时间单位为 ms)

int count = selector.select(long timeout);

方法3,不会阻塞,也就是不管有没有事件,立刻返回,自己根据返回值检查是否有事件

int count = selector.selectNow();

💡 select 何时不阻塞
  • 事件发生时

    • 客户端发起连接请求,会触发 accept 事件

    • 客户端发送数据过来,客户端正常、异常关闭时,都会触发 read 事件,另外如果发送的数据大于 buffer 缓冲区,会触发多次读取事件

    • channel 可写,会触发 write 事件

    • 在 linux 下 nio bug 发生时

  • 调用 selector.wakeup()

  • 调用 selector.close()

  • selector 所在线程 interrupt

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1:25万基础电子地图(云南版)

我们在《50幅1:25万基础电子地图&#xff08;四川版&#xff09;》一文中&#xff0c;为你分享过四川的50幅基础电子地图。 现在我们再为你分享云南的1&#xff1a;25万基础电子地图&#xff0c;你可以在文末查看该数据的领取方法。 基础电子地图云南版 下载后可以看到该数据…

【S32K 进阶之旅】 将 EB 配置生成的 MCAL 代码集成到 S32DS 中

本文介绍如何使用 S32DS 进行 AUTOSAR MCAL 工程的编译和调试&#xff0c;重点在于将 EB 配置生成的 MCAL 代码集成到 S32DS 中。 虽然配置过程较为繁琐&#xff0c;实操过一遍就会熟悉整个工程的框架。以后每次在 EB 中更新配置&#xff0c;生成代码的文件夹已经集成在 S32DS…

代码随想录——分割回文串(Leetcode 131)

题目链接 回溯 class Solution {List<List<String>> res new ArrayList<List<String>>();List<String> list new ArrayList<String>();public List<List<String>> partition(String s) {backtracking(s, 0);return res;}p…

博瓦科技产品亮相湖北安博会啦!!!

6月12日&#xff0c;第二十三届2024中国&#xff08;武汉&#xff09;社会公共安全产品暨数字城市产业展览会&#xff08;简称&#xff1a;湖北安博会&#xff09;在武汉国际会展中心隆重开幕。作为行业内最具影响力的展会之一&#xff0c;此次盛会将汇聚来自全球的顶尖企业、专…

AbMole带你探索细胞的“铁”门:Piezo1通道在椎间盘退变中的关键角色

在生物医学领域&#xff0c;铁是细胞功能不可或缺的元素&#xff0c;但铁的异常积累却可能成为细胞的“隐形杀手”。最近&#xff0c;一项发表在《Bone Research》上的研究&#xff0c;为我们揭开了铁代谢与椎间盘退变之间神秘联系的一角。这项研究不仅深化了我们对铁离子通道P…

长难句打卡6.17

At a time when Thomas Piketty and other economists are warning of rising inequality and the increasing power of inherited wealth, it is bizarre that wealthy aristocratic families should still be the symbolic heart of modern democratic states. 在托马斯皮凯…

深入理解MySQL字符集

一、字符集介绍 字符集&#xff08;Character Set&#xff09;是多个字符的集合&#xff0c;它规定了字符在计算机中的编码方式。以下是关于字符集的详细介绍&#xff1a; 1. 字符集的定义与作用 字符集是各种文字和符号的总称&#xff0c;包括各国家文字、标点符号、图形符号…

本地数据如何正确的导入SOLIDWORKS PDM系统

SOLIDWORKS 产品数据管理 (PDM) 解决方案可帮助您控制设计数据&#xff0c;并且从本质上改进您的团队就产品开发进行管理和协作的方式。使用 SOLIDWORKS PDM Professional&#xff0c;您的团队能够&#xff1a;1. 安全地存储和索引设计数据以实现快速检索&#xff1b;2. 打消关…

【Git】-- 添加公钥到 github 或者gitlab上

仅针对系统&#xff1a;mac os 、 unix、linux 1、检查是否有 id_rsa.pub $ cd ~ $ ls -al ~/.ssh 注意&#xff1a;若已有 id_rsa.pub&#xff0c;则必要执行 第二步&#xff0c;避免覆盖掉原有正常的公钥。 配置多个 git 账号请参考&#xff1a;同一台电脑配置多个git账…

使用RLHF推动翻译偏好建模:低成本实现“信达雅”

在机器翻译领域&#xff0c;“忠实度(信)”、“表现力(达)”、“优雅性(雅)”一直是研究者们不懈追求的目标。然而&#xff0c;传统的评估指标如BLEU并不能完全符合人类对翻译质量的偏好。为了解决这一挑战&#xff0c;复旦大学自然语言处理实验室与复旦大学外文学院携手合作&a…

利用原生HTML + CSS + JS实现歌词滚动

对于很多音乐APP&#xff0c;都有这么一个功能&#xff0c;就是根据歌曲的进度来控制对应的歌词滚动&#xff0c;如下图所示&#xff1a; 大概这样的效果&#xff0c;我此次是使用原生的HTMLCSSJS来实现的&#xff0c;以下是具体的实现过程。 1. 数据获取与处理 对于数据来源&…

Qt中利用QTextBrowser控件设计日志窗口

我们一般使用Qt开发应用程序时&#xff0c;都有将控制台窗口去掉。但是&#xff0c;有时候又需要查看一些调试信息&#xff0c;一般的处理方式是把log写到一个文件中。本文介绍以下日志窗口&#xff0c;可以更方便的查看日志信息。 UI设计 推拽UI控件&#xff0c;修改默认背景…

05眼动识别软件详情2波形优化

对应视频链接点击直达 01项目点击下载&#xff0c;可直接运行&#xff08;含数据库&#xff09; 05眼动识别软件详情2 对应视频链接点击直达期望的数据展示数据波形对比如何实现几种常用滤波介绍维纳滤波巴特沃斯滤波器中值滤波排序滤波 推荐 结语其他以下是废话 原始数据的波…

Objective-C 学习笔记 | KVC(key-value coding)

Objective-C 学习笔记 | KVC&#xff08;key-value coding&#xff09; Objective-C 学习笔记 | KVC&#xff08;key-value coding&#xff09;非对象类型Key 路径 Objective-C 学习笔记 | KVC&#xff08;key-value coding&#xff09; KVC 可以让程序通过名称直接存取属性&a…

CentOS 5(CentOS 6、Redhat 6)服务器配置VNC

一、配置服务器yum源 yum源&#xff08;本地、华为云、阿里云、网易&#xff09; 二、使用yum安装vnc服务 1、检查系统是否安装了vnc 和 vncserver&#xff0c; rpm -qa | grep vnc如果没有安装那就行自行下载安装&#xff08;我这里用yum安装了&#xff0c;vncserver安装需…

让你的网页动起来 - 轻松实现 JavaScript 拖拽功能

效果展示 实现 要实现该效果需要运用 HTML5 的 dragstart 拖放操作事件 通过去开启dragstart监听拖放操作事件就能实现图片的拖动 <div class"empty"><div class"fill" draggable"true"></div> </div>本例子中我们对…

基于深度学习的鸟类检测识别系统【python源码+Pyqt5界面+数据集+训练代码 MX_003期】

简介&#xff1a; 基于深度学习的鸟类检测识别系统在当今世界中具有广泛的应用前景。系统不仅可以帮助生态学家和保护人员监测和保护鸟类种群&#xff0c;还能在农业管理、城市生态监测以及科学研究领域发挥重要作用。通过自动化的图像识别技术&#xff0c;可以实现对鸟类种类、…

汽车传动系统为汽车动力总成重要组成部分 我国市场参与者数量不断增长

汽车传动系统为汽车动力总成重要组成部分 我国市场参与者数量不断增长 汽车系统主要包括动力系统、制动系统、传动系统、转向系统、行驶系统、燃油供给系统、照明系统以及电器系统。汽车传动系统指能够将发动机产生的动力转化为车辆行驶驱动力的动力传递装置。汽车传动系统为汽…

学生用小台灯什么牌子的好?五大强劲护眼台灯牌子分享

在这个数码时代&#xff0c;人们对屏幕的依赖程度越来越高&#xff0c;尤其是孩子们。他们不仅在学校里需要长时间盯着教科书&#xff0c;还会在学习和娱乐中使用各种数码设备。然而&#xff0c;这也使得眼睛健康问题逐渐凸显&#xff0c;尤其是儿童近视的问题。为了保护视力&a…

Inpaint软件下载附加详细安装教程

​Inpaint是一款由Maxim Gapchenko开发的图像处理软件&#xff0c;它可以帮助用户轻松地去除图像中的水印和其他不需要的元素&#xff0c;这个软件的核心技术是基于图像处理算法的&#xff0c;它可以自动识别图片中的像素&#xff0c;并用周围的颜色进行替换&#xff0c;使得图…