IO 与 NIO

优质博文:IT-BLOG-CN

一、阻塞IO / 非阻塞NIO

阻塞IO:当一条线程执行read()或者write()方法时,这条线程会一直阻塞直到读取到了一些数据或者要写出去的数据已经全部写出,在这期间这条线程不能做任何其他的事情。

非阻塞NIONIO与原有的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的操作。NIO将以更加高效的方式进行文件读写操作。JAVA NIO的核心在于:通道Channel和缓冲区Buffer。通道表示打开IO设备(例如:文件、套接字)的连接。若需要使用NIO系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区。对数据进行处理。

二、传统IO测试代码如下

当出现accept()read()等方法是就会阻塞。

/*** 传统socket服务端* @author -zhengzx-*/
public class OioServer {@SuppressWarnings("resource")public static void main(String[] args) throws Exception {//创建socket服务,监听10101端口ServerSocket server=new ServerSocket(10101);System.out.println("服务器启动!");while(true){//获取一个套接字(阻塞)final Socket socket = server.accept();//(测试时可以通过:telnet 127.0.0.1 10101。进行测试)System.out.println("来个一个新客户端!");//业务处理handler(socket);}}/*** 读取数据* @param socket* @throws Exception*/public static void handler(Socket socket){try {byte[] bytes = new byte[1024];InputStream inputStream = socket.getInputStream();while(true){//读取数据(阻塞)int read = inputStream.read(bytes);if(read != -1){System.out.println(new String(bytes, 0, read));}else{break;}}} catch (Exception e) {e.printStackTrace();}finally{try {System.out.println("socket关闭");socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

三、阻塞 IO解决办法

可以通过线程池创建多线程,为每一次连接创建一个新的线程来执行。问题是对于长连接而言,线程过多时会严重消耗系统资源导致性能下降。比较适合短连接的应用。

public static void main(String[] args) throws Exception {//创建线程池(可以通过线程解决阻塞问题、问题:每次连接都会创建一个线程,特别是长连接时特别消耗系统资源)ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();//创建socket服务,监听10101端口ServerSocket server=new ServerSocket(10101);System.out.println("服务器启动!");while(true){//获取一个套接字(阻塞)final Socket socket = server.accept();//(测试时可以通过:telnet 127.0.0.1 10101。进行测试)System.out.println("来个一个新客户端!");newCachedThreadPool.execute(new Runnable() {@Overridepublic void run() {//业务处理handler(socket);}});}
}

四、NIO 的非阻塞模式

Java NIO有阻塞模式和非阻塞模式,阻塞模式的NIO除了使用Buffer存储数据外和IO基本没有区别,允许一条线程从Channel中读取数据,通过返回值来判断buffer中是否有数据,如果没有数据,NIO不会阻塞,因为不阻塞这条线程就可以去做其他的事情,过一段时间再回来判断一下有没有数据。

*SelectorsJava NIOselectors允许一条线程去监控多个channels的输入,你可以向一个selector上注册多个channel,然后调用selectorselect()方法判断是否有新的连接进来或者已经在selector上注册时channel是否有数据进入。selector的机制让一个线程管理多个channel变得简单。

五、NIO示例代码如下

客户端使用SocketChannel,服务端使用ServerSocketChannel获取通道

public class NIOServerSocket {//定义一个socket入口private ServerSocketChannel serverSocket;//定义一个监听器Selector selector;public static void main(String[] args) throws IOException {NIOServerSocket nio =new NIOServerSocket();nio.initServer(8000);nio.listen();}public void initServer(int port) throws IOException {//获取一个serverSocket通道serverSocket = ServerSocketChannel.open();//设置为非阻塞状态(分为阻塞和非阻塞两种情况)serverSocket.configureBlocking(false);//将通道对应的serverSocketChannel绑定到端口上serverSocket.socket().bind(new InetSocketAddress(port));//获取一个通道管理器this.selector = Selector.open();//将通道管理器与通道进行绑定,并赋值SelectionKey.OP_ACCEPT事件//注册后,当事件到达后,select.select()会返回,如果没有返回,就一直阻塞。serverSocket.register(selector, SelectionKey.OP_ACCEPT);}public void listen() throws IOException {System.out.println("服务器启动");//轮询访问select.select()while(true) {//当事件到达时返回,否则一直阻塞Channel channel = selector.select();//获取selector中选中项的迭代器,相中的项为注册事件。Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();while(iterator.hasNext()) {SelectionKey selectionKey = iterator.next();//删除已选的key,防止重复处理iterator.remove();handler(selectionKey);}}}public void handler(SelectionKey key) throws IOException {if(key.isAcceptable()) {handlerAccept(key);}else if(key.isReadable()) {handlerRead(key);}}public void handlerAccept(SelectionKey key) throws IOException {//获取以有的通道ServerSocketChannel channel = (ServerSocketChannel) key.channel();//获取和客户端连接的通道SocketChannel accept = channel.accept();//设置为非阻塞accept.configureBlocking(false);// 在这里可以给客户端发送信息哦System.out.println("新的客户端连接");//连接成功之后,为了读取客户端传送的消息,需要设置读权限accept.register(selector, SelectionKey.OP_READ);}public void handlerRead(SelectionKey key) throws IOException {//服务器可读取消息,获取事件发生的Socket通道SocketChannel channel = (SocketChannel) key.channel();//创建读取内容的缓存区bufferByteBuffer buffer = ByteBuffer.allocate(1024);int read = channel.read(buffer);if(read > 0) {byte[] array = buffer.array();String msg = new String(array).trim();System.out.println("服务端收到信息:" + msg);//会写ByteBuffer byteBuffer = ByteBuffer.wrap("success".getBytes());channel.write(byteBuffer);}else {System.out.println("客户端关闭");key.cancel();}}
}

六 、selector.select()

selector.select()虽阻塞,但可以通过selector.wakeup()唤醒selector执行,也可以通过selector.select(int timeout)设置时间限制,timeout时间后唤醒 selector

七、NIO提高性能

添加多线程,一个线程对应一个selector,端口的监听可以单独创建一个selector。(既Netty的工作原理)

总结: NIO允许你用一个单独的线程或几个线程管理很多个channels(网络的或者文件的),代价是程序的处理和处理IO相比更加复杂。如果你需要同时管理成千上万的连接,但是每个连接只发送少量数据,例如一个聊天服务器,用NIO实现会更好一些,相似的,如果你需要保持很多个到其他电脑的连接,例如P2P网络,用一个单独的线程来管理所有出口连接是比较合适的。

IO:如果你只有少量的连接但是每个连接都占有很高的带宽,同时发送很多数据,传统的IO会更适合

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

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

相关文章

记录踩过的坑-macOS下使用VS Code

目录 切换主题 安装插件 搭建Python开发环境 装Python插件 配置解释器 打开项目 打开终端 切换主题 安装插件 方法1 方法2 搭建Python开发环境 装Python插件 配置解释器 假设解释器已经通过Anaconda建好&#xff0c;只需要在VS Code中关联。 打开项目 打开终端

ArmV8架构

Armv8/armv9架构入门指南 — Armv8/armv9架构入门指南 v1.0 documentation 上面只是给了一个比较好的参考文档 其他内容待补充

网络-httpclient调用https服务端绕过证书的方法

httpclient调用https服务端绕过证书的方法 在日常开发或者测试中&#xff0c;通常会遇到需要用httpclient客户端调用对方http是服务器的场景&#xff0c;由于没有证书&#xff0c;所以直接是无法调用的。采用下面的方法可以绕过证书验证&#xff1a; TrustManager[] trustAll…

AutoSAR(基础入门篇)13.5-Mcal Mcu时钟的配置

目录 一、EB的Mcu模块结构 二、时钟的配置 对Mcu的配置主要就是其时钟树的配置,但是EB将GTM、ERU等很多重要的模块也都放在了Mcu里面做配置,所以这里的Mcu是一个很庞大的模块, 我们目前只讲时钟树的部分 一、EB的Mcu模块结构 1. 所有的模块都基本上是这么些配置类别,Mc…

单词级文本攻击—论文阅读

TAAD2.2论文概览 0.前言1-101.Bridge the Gap Between CV and NLP! A Gradient-based Textual Adversarial Attack Frameworka. 背景b. 方法c. 结果d. 论文及代码 2.TextHacker: Learning based Hybrid Local Search Algorithm for Text Hard-label Adversarial Attacka. 背景b…

阅读笔记 | Transformers in Time Series: A Survey

阅读论文&#xff1a; Wen, Qingsong, et al. “Transformers in time series: A survey.” arXiv preprint arXiv:2202.07125 (2022). 这篇综述主要对基于Transformer的时序建模方法进行介绍。论文首先简单介绍了Transformer的基本原理&#xff0c;包括位置编码、多头注意力机…

OPENAI SORA:未来视频创作的新引擎——浅析其背后的人工智能算法

Sora - 探索AI视频模型的无限可能 随着人工智能技术的飞速发展&#xff0c;AI视频模型已成为科技领域的新热点。而在这个浪潮中&#xff0c;OpenAI推出的首个AI视频模型Sora&#xff0c;以其卓越的性能和前瞻性的技术&#xff0c;引领着AI视频领域的创新发展。本文将探讨SORA的…

回归预测 | Matlab实现RIME-BP霜冰算法优化BP神经网络多变量回归预测

回归预测 | Matlab实现RIME-BP霜冰算法优化BP神经网络多变量回归预测 目录 回归预测 | Matlab实现RIME-BP霜冰算法优化BP神经网络多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现RIME-BP霜冰算法优化BP神经网络多变量回归预测&#xff08;完整…

自动化测试介绍、selenium用法(自动化测试框架+爬虫可用)

文章目录 一、自动化测试1、什么是自动化测试&#xff1f;2、手工测试 vs 自动化测试3、自动化测试常见误区4、自动化测试的优劣5、自动化测试分层6、什么项目适合自动化测试 二、Selenuim1、小例子2、用法3、页面操作获取输入内容模拟点击清空文本元素拖拽frame切换窗口切换/标…

十五 超级数据查看器 讲解稿 外观设置

十五 超级数据查看器 讲解稿 外观设置 视频讲座地址 讲解稿全文: 大家好&#xff0c;今天讲解超级数据查看器,详情界面的外观设置。 首先&#xff0c;我们打开超级数据查看器。 本节课以成语词典为例来做讲述。 我们打开成语词典这个表&#xff0c;随便选一条记录点击&#x…

AutoSAR(基础入门篇)13.4-Mcal Dio代码分析

目录 一、文件结构 二、动态代码 1、arxml文件 2、Dio_Cfg.h 3、Dio_PBCfg.c 4、小结

【虚拟机安装centos7后找不到网卡问题】

最近开始学习linux&#xff0c;看着传智播客的教学视频学习&#xff0c;里面老师用的是centos6.5&#xff0c;我这边装的是centos7最新版的 结果到了网络配置的这一节&#xff0c;卡了我好久。 我在centos一直找不到我的网卡eth0&#xff0c;只有一个回环网口&#xff0c;在/…

什么是MVC和MVVM

**MVC和MVVM是两种流行的软件架构模式&#xff0c;它们在前端开发中被广泛采用来组织代码和管理应用程序的复杂性**。具体如下&#xff1a; MVC&#xff08;Model-View-Controller&#xff09;&#xff1a; 1. 模型&#xff08;Model&#xff09;&#xff1a;负责管理数据和业…

软考高级:主动攻击和被动攻击概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

第五套CCF信息学奥赛c++练习题 CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(选择题)

第五套中小学信息学奥赛CSP-J考前冲刺题 1、不同类型的存储器组成了多层次结构的存储器体系,按存取速度从快到慢排列的是 A、快存/辅存/主存 B、外存/主存/辅存 C、快存/主存/辅存 D、主存/辅存/外存 答案&#xff1a;C 考点分析&#xff1a;主要考查计算机相关知识&…

静态链表(3)

尾插函数 尾插就比头插多了一步找尾巴&#xff0c;其他均一样 尾插步骤画图 1.找到空闲结点3 2.空链踢空点&#xff0c;穿透删除 先绑后面 再接前面&#xff0c;就完成插入了 综上所述&#xff0c;静态链表就是处理两条链表&#xff0c;静态链表总的执行一次插入或删除&#…

Netty NIO ByteBuffer 简单实验

1.概要 准备学一下Netty,先从NIO的三大组件开始。先ByteBuffer 2.代码 2.1 主函数 package com.xjc.springcloundtest;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio…

【大厂AI课学习笔记NO.62】模型的部署

我们历尽千辛万苦&#xff0c;总算要部署模型了。这个系列也写到62篇&#xff0c;不要着急&#xff0c;后面还有很多。 这周偷懒了&#xff0c;一天放出太多的文章&#xff0c;大家可能有些吃不消&#xff0c;从下周开始&#xff0c;本系列将正常更新。 这套大厂AI课&#xf…

[python] dict类型变量写在文件中

在Python中&#xff0c;如果你想要将一个字典变量以具有可读性的格式写入文件&#xff0c;并且指定缩进为2个空格&#xff0c;你可以使用json模块来实现。json模块提供了一种很方便的方法来进行序列化和反序列化Python对象。下面是一个具体的示例&#xff1a; 字典变量以具有可…

【剑指offer--C/C++】JZ3 数组中重复的数字

一、题目 二、本人思路及代码 这道题目它要求的时间空间利用率都是n&#xff0c;那么可以考虑创建一个长度为n的数组repeat初始化为0&#xff0c;下标代码出现的数字&#xff0c;下标对应的数组内容代表该下标数字出现的次数。然后遍历提供的数组&#xff0c;每出现一个数字&a…