NIO模型和优化点
NIO
一:概述:
NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)。传统IO是基于字节流和字符流进行操作(基于流),而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
二:三者关系
1:一个线程对应一个Selector
2:一个Selector对应多个Channel
3:一个channel对应一个buffer
4:一个buffer是一个内存块(数组)
5:一个channel对应一个客户端连接
6:一个channel绑定一个端口,多个channel可以绑定同一个端口
三:NIO解决问题/存在问题
1:解决的问题
-
:一个线程可以接收多个客户端连接
-
:基于缓存,效率更高(BIO基于流)
-
:不同的消息分发到不同的channel中
-
:NIO解决的根本问题就是一个线程多个客户端
2:存在问题
1):若有消息处理太慢,其它channel消息会被卡住,同时其它客户端连接也无法接入。
三:代码演示
下面代码是两个selector,一个是连接selector,一个是读selector
-
package com.test.io;
-
-
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 NIOTest {
-
-
public static void main(String[] args) throws Exception {
-
//获取一个Selector
-
Selector selector = Selector.open();
-
/**
-
* 创建一个连接类型的通道
-
* 设置为不阻塞
-
* 绑定端口6666
-
* 注册到selector
-
*/
-
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
-
serverSocketChannel.configureBlocking(false);
-
serverSocketChannel.bind(new InetSocketAddress(6666));
-
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
-
while (true){
-
/**
-
* 未有连接或消息前阻塞在selector
-
* 有消息后,继续执行
-
*/
-
selector.select();
-
-
/**
-
* 获取消息中的SelectionKey的集合
-
* 每次有消息过来都会有一个唯一对的SelectionKey添加到Selector中Set集合中
-
* SelectionKey保存者channel信息
-
*/
-
Set<SelectionKey> selectionKeys = selector.selectedKeys();//当前所有有消息的事件
-
Iterator<SelectionKey> it = selectionKeys.iterator();
-
while (it.hasNext()){//遍历所有消息事件,输出消息
-
SelectionKey selectionKey = it.next();
-
//获取到消息事件后,立即移除该消息事件
-
selectionKeys.remove(selectionKey);
-
//判断消息事件类型,是连接消息 还是普通消息
-
if(selectionKey.isValid() && selectionKey.isAcceptable()){//连接消息
-
/**
-
* accept是一个阻塞方法,在此处基本不会阻塞,正是因为有消息才到达这里
-
* 为新的连接生成一个channel
-
* channel设置为不阻塞
-
* 注册到selector
-
*/
-
SocketChannel channel = serverSocketChannel.accept();//与it.hasNext()一个一个地对应,保证channel与SelectionKey对应
-
channel.configureBlocking(false);
-
channel.register(selector,SelectionKey.OP_READ);
-
}
-
if(selectionKey.isValid() && selectionKey.isReadable()){//普通消息
-
/**
-
* 获取消息的通道
-
*/
-
SocketChannel channel = (SocketChannel) selectionKey.channel();
-
ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
-
channel.read(byteBuffer);
-
System.out.println("客户端消息:" byteBuffer.toString());
-
}
-
}
-
}
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhhagiia
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13