java网络编程-nio学习:阻塞和非阻塞
一、阻塞
-
阻塞模式下,相关方法都会导致线程暂停
-
ServerSocketChannel.accept 会在没有连接建立时让线程暂停
-
SocketChannel.read 会在没有数据可读时让线程暂停
-
阻塞的表现其实就是线程暂停了,暂停期间不会占用 cpu,但线程相当于闲置
-
-
单线程下,阻塞方法之间相互影响,几乎不能正常工作,需要多线程支持
-
但多线程下,有新的问题,体现在以下方面
-
32 位 jvm 一个线程 320k,64 位 jvm 一个线程 1024k,如果连接数过多,必然导致 OOM,并且线程太多,反而会因为频繁上下文切换导致性能降低
-
可以采用线程池技术来减少线程数和线程上下文切换,但治标不治本,如果有很多连接建立,但长时间 inactive,会阻塞线程池中所有线程,因此不适合长连接,只适合短连接。
-
服务端事例代码:
// 使用 nio 来理解阻塞模式, 单线程
// 0. ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
// 1. 创建了服务器
ServerSocketChannel ssc = ServerSocketChannel.open();// 2. 绑定监听端口
ssc.bind(new InetSocketAddress(8080));// 3. 连接集合
List<SocketChannel> channels = new ArrayList<>();
while (true) {// 4. accept 建立与客户端连接, SocketChannel 用来与客户端之间通信log.debug("connecting...");SocketChannel sc = ssc.accept(); // 阻塞方法,线程停止运行log.debug("connected... {}", sc);channels.add(sc);for (SocketChannel channel : channels) {// 5. 接收客户端发送的数据log.debug("before read... {}", channel);channel.read(buffer); // 阻塞方法,线程停止运行buffer.flip();debugRead(buffer);buffer.clear();log.debug("after read...{}", channel);}
}
客户端:
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 改进的地方)
服务器端demo代码,客户端代码不变
// 使用 nio 来理解非阻塞模式, 单线程
// 0. ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
// 1. 创建了服务器
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false); // 非阻塞模式
// 2. 绑定监听端口
ssc.bind(new InetSocketAddress(8080));
// 3. 连接集合
List<SocketChannel> channels = new ArrayList<>();
while (true) {// 4. accept 建立与客户端连接, SocketChannel 用来与客户端之间通信SocketChannel sc = ssc.accept(); // 非阻塞,线程还会继续运行,如果没有连接建立,但sc是nullif (sc != null) {log.debug("connected... {}", sc);sc.configureBlocking(false); // 非阻塞模式channels.add(sc);}for (SocketChannel channel : channels) {// 5. 接收客户端发送的数据int read = channel.read(buffer);// 非阻塞,线程仍然会继续运行,如果没有读到数据,read 返回 0if (read > 0) {buffer.flip();debugRead(buffer);buffer.clear();log.debug("after read...{}", channel);}}
}
三、多路复用
单线程可以配合 Selector 完成对多个 Channel 可读写事件的监控,这称之为多路复用。
-
多路复用仅针对网络 IO、普通文件 IO 没法利用多路复用
-
如果不用 Selector 的非阻塞模式,线程大部分时间都在做无用功,而 Selector 能够保证
-
有可连接事件时才去连接
-
有可读事件才去读取
-
有可写事件才去写入
-
限于网络传输能力,Channel 未必时时可写,一旦 Channel 可写,会触发 Selector 的可写事件
-
-

好处
-
一个线程配合 selector 就可以监控多个 channel 的事件,事件发生线程才去处理。避免非阻塞模式下所做无用功
-
让这个线程能够被充分利用
-
节约了线程的数量
-
减少了线程上下文切换
创建
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
相关文章:
java网络编程-nio学习:阻塞和非阻塞
一、阻塞 阻塞模式下,相关方法都会导致线程暂停 ServerSocketChannel.accept 会在没有连接建立时让线程暂停 SocketChannel.read 会在没有数据可读时让线程暂停 阻塞的表现其实就是线程暂停了,暂停期间不会占用 cpu,但线程相当于闲置 单线…...
JVM-JMM内存模型(happens-before、volatile)
前言 由于计算机的存储设备与处理器的运算速度有几个数量级的差距所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲。 将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算…...
算法leetcode|37. 解数独(rust重拳出击)
文章目录37. 解数独:样例 1:提示:分析:题解:rustgoccpythonjava37. 解数独: 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现…...
SpringBoot整合Dubbo
目录1、dubbo简介2、dubbo解决了什么问题3、环境准备4、项目搭建5、总结springboot整合feign可参考我另外一篇文章SpringBoot集成Feign 1、dubbo简介 Apache Dubbo 最初在 2008 年由 Alibaba 捐献开源,很快成为了国内开源服务框架选型的事实标准框架 ,…...
[软件工程导论(第六版)]第9章 面向对象方法学引论(课后习题详解)
文章目录1. 什么是面向对象方法学?它有哪些优点?2. 什么是“对象”?它与传统的数据有何异同?3. 什么是“类”?4. 什么是“继承”?5. 什么是模型?开发软件为何要建模?6. 什么是对象模…...
光学分辨率光声显微镜中基于深度学习的运动校正算法
在这项研究中,我们提出了一种基于深度学习的方法来校正光学分辨率光声显微镜 (OR-PAM) 中的运动伪影。该方法是一种卷积神经网络,它从具有运动伪影的输入原始数据建立端到端映射,以输出校正后的图像。首先,我们进行了仿真研究&…...
浅谈UG二次开发中使用的FindObject
一般我们在业务逻辑里想查找一个Object的时候,会调用FindObject、GetObject、NxObjectManager.Get,不管是上述哪种实现,都是在内存中找东西,找到了就返回对象,否则返回null,但不会触发加载。 这里我分别从建…...
贪心原理及刷题
更新中 概念 使用贪心需要满足,上一步的局部最优解能推出这一步的局部最优解,直到得到全局最优解 而dp这一步的局部最优,不一定来源上一步的局部最优,而可能与更早的解有关,同时dp转移方程的推导也比较复杂 122. 买卖股票的最佳时机 II - 力扣(LeetCode) 这道题是典…...
2023赏金计划:Coremail SRC漏洞征集与样本奖励火热进行中
赏金活动一:Coremail SRC漏洞奖励计划 01 活动背景 2023年1月,Coremail安全应急响应中心(Coremail SRC)正式上线启用,面向公众收集安全漏洞信息与安全情报。Coremail SRC旨在联合众多安全专家、白帽子研究员共同发现…...
简记:清理指定后缀名文件的 powerhsell 小脚本
清理指定后缀名文件的 powerhsell 小脚本jcLee95:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/details/129121074 1.介绍 相关工具代码 2.目…...
问题记录:mac系统偏好设置不展示mysql
Mac新系统升级(10.14.5)后未从appstore下载的软件在安装时会提示安装包已损坏之类的东东,这是因为没有打开“设置”—“安全与隐私”中的“任何来源”造成的,可是升级后的10.14.5却没有这个选项。 那么macOS 10.14.5以上允许任何…...
网络计划--时间参数的计算和优化
根据网络图的基本概念和原则绘制出网络图之后,我们可以计算网络图中有关的时间参数,主要目的是找出关键路线,为网络计划的优化、调整和执行提供明确的时间概念。如下图中从始点①到终点⑧共有4条路线,可以分别计算出每条路线所需的…...
1.2.7存储结构-磁盘管理:磁盘移臂调度算法、先来先服务(FCFS)、最短寻道时间优先(SSTF)、扫描算法(SCAN)、循环扫描(CSCAN)
1.2.7存储结构-磁盘管理:磁盘移臂调度算法、先来先服务(FCFS)、最短寻道时间优先(SSTF)、扫描算法(SCAN)、循环扫描(CSCAN)先来先服务(FCFS)最短寻…...
2022年AI顶级论文 —生成模型之年(上)
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 过去十年来,人工智能技术在持续提高和飞速发展,并不断冲击着人类的认知。 2012年,在ImageNet图像识别挑战赛中,一种神经网络模型(AlexNet&…...
Linux下程序调试的方法【GDB】GDB相关命令和基础操作(命令收藏)
目录 1、编译 2、启动gdb调试 2.1 直接运行 2.2 运行gdb后使用run命令 2.3 调试已运行的程序 3、图形界面提示 4、调试命令 1、查看源码 2、运⾏程序/查看运⾏信息 3、设置断点 5、单步/跳步执⾏ 6、分割窗口 7、其他命令 8、相关参数 1、编译 在编译时要加上-g选…...
使用frp配置内网机器访问
frp简介 frp 是一个开源、简洁易用、高性能的内网穿透和反向代理软件,支持 tcp, udp, http, https等协议。frp 项目官网是 https://github.com/fatedier/frp,软件下载地址为https://github.com/fatedier/frp/releases frp工作原理 服务端运行…...
简述7个流行的强化学习算法及代码实现!
目前流行的强化学习算法包括 Q-learning、SARSA、DDPG、A2C、PPO、DQN 和 TRPO。这些算法已被用于在游戏、机器人和决策制定等各种应用中,并且这些流行的算法还在不断发展和改进,本文我们将对其做一个简单的介绍。1、Q-learningQ-learning:Q-…...
朗润国际期货招商:地方政府工作报告中对于促进消费
地方政府工作报告中对于促进消费 北京:把恢复和扩大消费摆在优先位置。加紧推进国际消费中心城市建设、深化商圈改造提升行动、统筹推进物流基地规划建设,强化新消费地标载体建设、试点建设80个“一刻钟便民生活圈”,提高生活性服务重品质。…...
前端性能优化的一些技巧(90% chatGpt生成)
终于弄好了chatGpt的账号,赶紧来体验一波。先来一波结论,这篇文章的主要内容来源,90%是用chatGpt生成的。先上chatGpt的生成的结果:作为一名懒惰的程序员,chatGpt会帮助我变得更懒...,好了下面开始文章的正…...
[软件工程导论(第六版)]第8章 维护(复习笔记)
文章目录8.1 软件维护的定义8.2 软件维护的特点8.3 软件维护过程8.4 软件的可维护性8.5 预防性维护8.6 软件再工程过程维护的基本任务:保证软件在一个相当长的时期能够正常运行软件工程的主要目的就是要提高软件的可维护性,减少软件维护所需要的工作量&a…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...
Python打卡训练营学习记录Day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
SpringSecurity+vue通用权限系统
SpringSecurityvue通用权限系统 采用主流的技术栈实现,Mysql数据库,SpringBoot2Mybatis Plus后端,redis缓存,安全框架 SpringSecurity ,Vue3.2Element Plus实现后台管理。基于JWT技术实现前后端分离。项目开发同时采 …...
