在高并发(持续大量的连接同时请求)场景中,之前的两种 BIO 优化方案都需要消耗大量的线程来维持连接。并且 CPU 在线程切换上消耗很大。

Java NIO 模型的主要优势:少量的线程就可以处理大量连接的请求

主要组成:

  1. Channel 通道:IO 传输发生时数据通过的入口
  2. Buffer 缓冲区:可以理解为数据在管道传输时的起点和终点
  3. Selector 选取器(IO监听器):负责监听 IO 事件

所用通道都向 Selector 注册,Selector 负责轮询检测,然后服务端进程会阻塞在 Selector 的 select() 方法,直到注册的通道有事件就绪。

代码示例 : NIOServer.java

package org.io.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;public class NIOServer {// 服务端通道private ServerSocketChannel serverChannel;// 选择器private Selector selector;// 默认服务绑定端口private static int DEFAULT_BIND_PORT = 9000;public NIOServer(int port) {initServer(port);}private void initServer(int port) {try {// 开启一个服务通道this.serverChannel = ServerSocketChannel.open();// 将通道绑定到指定端口this.serverChannel.bind( (port < 1 || port > 65535) ?new InetSocketAddress(DEFAULT_BIND_PORT) :new InetSocketAddress(port));// 将通道设置为非阻塞模式this.serverChannel.configureBlocking(false);// 打开一个 IO 监视器:Selectorthis.selector = Selector.open();// 将服务通道注册到 Selector 上,并在服务端通道注册 OP_ACCEPT 事件this.serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);} catch (IOException ioException) {ioException.printStackTrace();System.out.println("init exception: " + ioException);}}public void startServer() throws InterruptedException {while (true){System.out.println("Selector 巡查 IO 事件---------------开始");try {int ioEventCount = this.selector.select();  // 此处以收集到所有 IO 事件System.out.println("Selector 检测到:" + ioEventCount);} catch (IOException ioException) {ioException.printStackTrace();break;}// 对各个 IO 事件做出对应的响应Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()){SelectionKey key = iterator.next();iterator.remove();  //通过调用迭代器的 remove() 方法将这个键 key 从已选择键的集合中删除try {// 可接收连接 能注册SelectionKey.OP_ACCEPT事件的只有 ServerSocketChannel通道if (key.isAcceptable()) {System.out.println("监控到 OP_ACCEPT 连接事件");ServerSocketChannel server = (ServerSocketChannel) key.channel();// 接受客户端连接SocketChannel client = server.accept();System.out.println("Accept connection from " + client);client.configureBlocking(false); // 设置客户端通道非阻塞// 为客户端通道注册 OP_WRITE 和 OP_READ 事件SelectionKey clientKey = client.register(selector,SelectionKey.OP_WRITE |SelectionKey.OP_READ);// 为客户端通道添加一个数据缓存区ByteBuffer buffer = ByteBuffer.allocate(100);clientKey.attach(buffer);}// 可读数据if (key.isReadable()) {SocketChannel client = (SocketChannel) key.channel();ByteBuffer output = (ByteBuffer) key.attachment();int read = client.read(output);System.out.println("Read data from client: " + client);System.out.println("------------MSG : " + output.toString());}// 可写数据if (key.isWritable()) {SocketChannel client = (SocketChannel) key.channel();ByteBuffer output = (ByteBuffer) key.attachment();output.flip();client.write(output);output.compact();System.out.println("Write data to " + client);}} catch (IOException ioException) {ioException.printStackTrace();}}Thread.sleep(2000);// 为了观察控制台打印数据System.out.println("Selector 巡查 IO 事件---------------完成");}}public static void main(String[] args) throws InterruptedException {NIOServer nioServer = new NIOServer(DEFAULT_BIND_PORT);nioServer.startServer();}
}

Java NIO 模型代码示例相关推荐

  1. Python 调用 SCIP 求解器的选址模型代码示例

    本文介绍 Python 语言调用 SCIP 求解器,求解选址模型的代码示例. 安装 SCIP 和 PySCIPOpt 安装 SCIP 求解器的教程: SCIP | 数学规划求解器SCIP超详细的使用教 ...

  2. java NIO模型和三大核心原理

    1.NIO (1)基本介绍 1)Java NIO全程 java non-blocking IO,是指JDK提供的新API.从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NI ...

  3. jedispool redis哨兵_通过java哨兵JedisSentinelPool代码示例连接对配置的redis哨兵主从模式进行测试验证...

    一.前言 本文章通过关于java的jedis(2.6.0)的redis客户端连接驱动包,对配置的redis哨兵+主从读写模式配置进行示例代码验证,详细参见具体配置步骤&示例代码说明部分. 二. ...

  4. java并发编程代码示例_java并发编程之同步器代码示例

    java并发编程之同步器代码示例 发布时间:2020-09-08 16:53:41 来源:脚本之家 阅读:58 作者:Blessing_H 同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作 ...

  5. Java输入输出流代码示例

    写在前面: 该博文是为文章http://blog.csdn.net/whardl_yu/article/details/53223807补充的代码示例.主要为输入输出流的一些基础操作. 一. 功能:将 ...

  6. python 生产者-消费者模型 - 代码示例

    代码示例 #!/usr/bin/env python #encoding: utf-8 import threading import timecondition = threading.Condit ...

  7. java中po代码示例_java操作oracle常用的示例代码详解

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...

  8. Java操作MongoDB代码示例

    条件查询及数据插入:

  9. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  10. Java 7:项目代币中的代码示例

    该博客通过代码示例介绍了一些新的Java 7功能,这些功能在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更改确实简化了Java语言 ...

最新文章

  1. 在markdown里面插入特殊的符号
  2. (转载)网络编程释疑之:同步,异步,阻塞,非阻塞
  3. indexzero/http-server-2-使用
  4. 通过栈(Stack)实现对树的遍历
  5. jquery width,height,innerwidth,innerheight,outerwidth,outerheight方法
  6. WPS如何对文档加密,忘记密码又如何解密?
  7. Flash CS3无法导出测试影片问题解决
  8. vue 音乐进度条拖拽
  9. 基于Autoware制作高精地图(一)
  10. 阿尔法蛋机器人tf卡_科大讯飞阿尔法蛋tys1智能机器人常见问题解答
  11. 直波导与微环的耦合——Lumerical仿真1
  12. MATLAB | 面积图、饼状图、水平柱状图的斜线填充(阴影填充)
  13. 8月第2周业务风控关注 | 新氧加强内容审核并上线人脸识别技术
  14. 通过Wireshark来了解Zigbee协议
  15. 手机MTP模式连接电脑后文件夹显示不全 小米5s
  16. 【大厂面试题精选】UDP 和 TCP 核心知识总结
  17. 修改注册表锁定IE主页
  18. LogStash 简介
  19. 【Web/Tools系列】在MacbookPro M1芯片笔记本上安装EMCC
  20. IBM实习生笔试题目(2)

热门文章

  1. python 代码生成器_Python代码生成器(代码生成工具)V1.1 正式版
  2. 更改计算机图标大小得方法,更改图标大小【解决办法】
  3. 2021年烷基化工艺考试内容及烷基化工艺考试资料
  4. wiki admin.php,dokuwiki 重置管理员密码
  5. 多元函数的切向量和法向量
  6. 配置Jenkins及下载相关插件
  7. 企业网络规划和设计方案
  8. 声卡中的 line in line out
  9. Quartz定时任务框架(二):Trigger触发器详解
  10. Linux命令:查看服务器IP地址