文章目录

  • Non Blocking I/O 同步非阻塞模型
  • Code
    • Server
    • Client
    • 日志及需要优化的地方
    • 优化 (多路复用器)
  • 小结


Non Blocking I/O 同步非阻塞模型

同步非阻塞

一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理。

JDK1.4开始引入


Code

Server

package com.artisan.iomodel.nio;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;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:06* @mark: show me the code , change the world*/public class NioServer {// 保存客户端连接static List<SocketChannel> channelList = new ArrayList<>();public static void main(String[] args) throws IOException {// 创建NIO ServerSocketChannel,与BIO的serverSocket类似ServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 设置ServerSocketChannel为非阻塞serverSocket.configureBlocking(false);System.out.println("服务启动成功");while (true) {// 非阻塞模式accept方法不会阻塞,否则会阻塞// NIO的非阻塞是由操作系统内部实现的,底层调用了linux内核的accept函数SocketChannel socketChannel = serverSocket.accept();if (socketChannel != null) { // 如果有客户端进行连接System.out.println("连接成功");// 设置SocketChannel为非阻塞socketChannel.configureBlocking(false);// 保存客户端连接在List中channelList.add(socketChannel);}// 遍历连接进行数据读取Iterator<SocketChannel> iterator = channelList.iterator();while (iterator.hasNext()) {SocketChannel sc = iterator.next();ByteBuffer byteBuffer = ByteBuffer.allocate(128);// 非阻塞模式read方法不会阻塞,否则会阻塞int len = sc.read(byteBuffer);// 如果有数据,把数据打印出来if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客户端断开,把socket从集合中去掉iterator.remove();System.out.println("客户端断开连接");}}}}
}

Client

我们用cmd工具来连一下 , telnet 127.0.0.1 7777

回车,输入 ctrl + ]

发送消息


日志及需要优化的地方

举个例子,如果连接数太多的话,会有大量的无效遍历,假如有1万个连接,其中只有1000个连接有写数据,但是由于其他9000个连接并没有断开,我们还是要每次轮询遍历一万次,其中有十分之九的遍历都是无效的…是不是有点不妥当呢?


优化 (多路复用器)

为了优化这个问题 , NIO引入多路复用器

package com.artisan.iomodel.nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:50* @mark: show me the code , change the world*/
public class NioSelectorServer {public static void main(String[] args) throws IOException, InterruptedException {// 创建NIO ServerSocketChannelServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 设置ServerSocketChannel为非阻塞serverSocket.configureBlocking(false);// 打开Selector处理Channel,即创建epollSelector selector = Selector.open();// 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务启动成功");while (true) {// 阻塞等待需要处理的事件发生selector.select();// 获取selector中注册的全部事件的 SelectionKey 实例Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍历SelectionKey对事件进行处理while (iterator.hasNext()) {SelectionKey key = iterator.next();// 如果是OP_ACCEPT事件,则进行连接获取和事件注册if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);// 这里只注册了读事件,如果需要给客户端发送数据可以注册写事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客户端连接成功");} else if (key.isReadable()) {  // 如果是OP_READ事件,则进行读取和打印SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = socketChannel.read(byteBuffer);// 如果有数据,把数据打印出来if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客户端断开连接,关闭SocketSystem.out.println("客户端断开连接");socketChannel.close();}}//从事件集合里删除本次处理的key,防止下次select重复处理iterator.remove();}}}
}


小结

NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,但编程比较复杂

Netty - I/O模型之NIO相关推荐

  1. java nio oio_Java NIO框架Netty教程(十四) Netty中OIO模型(对比NIO)

    Netty中不光支持了Java中NIO模型,同时也提供了对OIO模型的支持.(New IO vs Old IO). 首先,在Netty中,切换OIO和NIO两种模式是非常方便的,只需要初始化不同的Ch ...

  2. java nio oio_Java NIO框架Netty教程(十四)-Netty中OIO模型(对比NIO)

    OneCoder这个周末搬家,并且新家目前还没有网络,本周的翻译的任务尚未完成,下周一起补上,先上一篇OIO和NIO对比的小研究. Netty中不光支持了Java中NIO模型,同时也提供了对OIO模型 ...

  3. 【Netty】Netty 简介 ( 原生 NIO 弊端 | Netty 框架 | Netty 版本 | 线程模型 | 线程 阻塞 IO 模型 | Reactor 模式引入 )

    文章目录 一. NIO 原生 API 弊端 二. Netty 简介 三. Netty 架构 四. Netty 版本 五. Netty 线程模型 六. 阻塞 IO 线程模型 七. 反应器 ( React ...

  4. Netty序章之BIO NIO AIO演变

    Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...

  5. 【Netty】从 BIO、NIO 聊到 Netty

    为了让你更好地了解 Netty 以及它诞生的原因,先从传统的网络编程说起吧! 还是要从 BIO 说起 传统的阻塞式通信流程 早期的 Java 网络相关的 API(java.net包) 使用 Socke ...

  6. Netty专题-(2)NIO三大核心

    在之前的文章Netty专题-(1)初识Netty中提到了NIO三大核心Selector . Channel 和 Buffer,所以在这一章重点会是介绍这三个核心. 1 缓冲区(Buffer) 1.1 ...

  7. 面试官:Netty的线程模型可不是Reactor这么简单

    笔者看来Netty的内核主要包括如下图三个部分: 其各个核心模块主要的职责如下: 内存管理 主要提高高效的内存管理,包含内存分配,内存回收. 网通通道 复制网络通信,例如实现对NIO.OIO等底层JA ...

  8. Netty之线程模型

    Reactor 线程模型: Reactor 是反应堆的意思,Reactor 模型是指通过一个或多个输入同时传递给服务处理器的服务请求的事件驱动处理模式.服务端程序处理传入多路请求,并将它们同步分派给请 ...

  9. Netty专题-(3)NIO网络编程

    之前在上一章Netty专题-(2)NIO三大核心中介绍了NIO的三大核心类Selector . Channel 和 Buffer,这一章我们将利用这些核心进行编程实现相关的一些功能.在正式进入编程之前 ...

最新文章

  1. matlab绘制bland-altman,制作Bland-Altman图的步骤和程序(以SPSS作图为例讲解)
  2. 【错误记录】Git 使用报错 ( git branch -a 仍能查询到已经删除的远程分支 )
  3. 类与接口(四)方法重载解析
  4. 元组-元组和格式化字符串
  5. 2020蓝桥杯省赛---java---B---5( REPEAT 程序)
  6. Arbitrage——判断正环Bellman-Ford/SPFA
  7. MQTT代理服务器特性对比
  8. 利用扩展欧几里得算法编程求逆元
  9. 聚类算法 距离矩阵_机器学习基础-层次聚类
  10. HTML静态网页--JavaScript-语法
  11. android路上的点点滴滴
  12. 思科防火墙配置命令(详细命令总结归纳)
  13. 【毕设教学】 经典单片机控制算法:PID - 嵌入式 物联网
  14. 【很有趣】用Python实现一个简单的人脸识别,原来我和这个明星如此相似
  15. 常见的企业流程再造模式
  16. asp dotnet core 从零开始创建一个 WebApi 服务
  17. mybatis官方文档中文版
  18. 重建oracle inventory
  19. 辐射避难所ol服务器维护,辐射避难所Online8月3日更新内容 育普雷斯顿up卡池
  20. 无人机停机坪是什么?有哪些作用?无人机自动巡检如何实现?

热门文章

  1. java的xms与xmx和服务器内存_JAVA_OPTS参数-Xms和-Xmx的作用
  2. 易语言 mysql 卡死_易语言操作MYsql 所有课程停发
  3. java 之在校期间最后一次实训记录
  4. android webview 多文件上传,Android中的webview支持页面中的文件上传实例代码
  5. 基于jquery的php分页,基于jQuery封装的分页组件
  6. Haskell 斐波那契 数列 递归实现
  7. 实用的才是最好的,教你如何以MATLAB的方式实现高等应用数学问题(二)
  8. MySQL从入门到精通50讲(十一)-MySQL正则表达式及事务
  9. tableau应用实战案例(二)-TABLEAU调用中国地图和Python获取地址的经纬度
  10. 深度学习100例 | 第33天:迁移学习-实战案例教程