千家信息网

Java NIO的知识点有哪些

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,今天小编给大家分享一下Java NIO的知识点有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起
千家信息网最后更新 2026年11月03日Java NIO的知识点有哪些

今天小编给大家分享一下Java NIO的知识点有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

No-Block 和Block IO 的区别:

一个典型的网络通讯步骤为: open (新建socket Chanel )--> connect( 尝试建立连接) --> accept( 连接被接受) --> read( 读取请求)send (输出结果)--> close( 连接关闭) 。

对于一个No-Block 的网络IO ,上面的每一步都是会马上返回的,当然返回的结果可能为null ,可能不为null ,这个要看下上文(context )决定。一般情况下,我们都是需要不为null 的结果,这个就需要我们在适当的时机,执行适当的步骤,这样就会得到我们想要的结果。何为适当的时机?这个下面会讲。

对于一个block 的网络IO ,上面的每一步执行的时候,如果没到适当的时机,当前线程就会被block 住,直到适当的时机,返回给你确定的结果。

当然对与No-Block 或者Block IO ,上面的每一步都有可能会抛出IOException 异常的。

NIO 编程接触的几个关键概念:

Buffer :是一块连续的内存块,是 NIO 数据读或写的中转地。Buffer 这篇blog 暂时略过不讲。

Chanel :数据的源头或者数据的目的地,用于向 buffer 提供数据或者读取 buffer 数据 ,异步 I/O 支持。

注意chanel 有2 类,一种叫SocketChanel, 一种叫ServerSocketChanel ,看名字我们就知道,一类是普通的socket chanel ,client 端和服务器端都用的,一类是专门用在server 端的。当然这个界限也不是绝对的,互为client 和server 的情况也是存在的。

Selector : chanel 事件的侦听者, 它能检测一个或多个通道 (channel) 上的事件,并将事件分发出去。使用一个 select 线程就能监听多个通道上的事件,并基于事件驱动触发相应的响应。

SelectionKey : chanel 上发生的事件, 包含了事件的状态信息和时间以及对应的 chanel 。

Chanel 的状态:

可连( Connectable ):当一个 Chanel 完成 socket 连接操作已完成或者已失败放弃时。

能连( Acceptable ):当一个 Chanel 已经准备好接受一个新的 socket 连接时。

可读( Readable ):当一个 Chanel 能被读时。

可写( Writable ):当一个 Chanel 能被写时。

结合对照上面的网络通讯步骤我们可以有以下推导出的结论:

当一个 Server Chanel 是 Connectable 时, client 端尝试 connect 才会成功。

当一个 Server Chanel 是 Acceptable 时, client 的连接请求被真正受理,一个新的 chanel 会被生成,并且记录了 localAdrress 和 remoteAddress. 为进一步读写做准备。

当一个 Chanel 是 Readable 时,我们从这个 Chanel 中读取数据才会成功。

当一个 Chanel 是 Writable 时,我们往这个 Chanel 中写数据才会成功。

记住一点,对于一个 No-Block 的 Chanel 来说,上面 4 个操作都会马上返回或者抛出 IOException ,但是是不是成功就难说了,前面就说了,我们在一个 Chanel 做操作的时候,我们要密切关注 Chanel 的当前状态。只有在知道 Chanel 的当前状态时,我们才能在这个 Chanel 上做最适当的操作。

聪明的你可能马上就会想到,要是你操作的 Chanel 的状态的转换信息能被你抓取,这些问题就迎刃而解了。对啦, NIO 就是这样设计的。一个 Chanel 可以注册一个 Selector (就像一个事件侦听器),而且你还要告知你想要要侦听的状态。用一段代码来说明下:

selector = SelectorProvider.provider().openSelector();  serverChannel1 = ServerSocketChannel.open();  serverChannel1.configureBlocking(false);  InetSocketAddress isa = new InetSocketAddress("localhost", 9999);  serverChannel1.socket().bind(isa);  serverChannel1.register(selector, SelectionKey.OP_ACCEPT);

这段代码的意思就是我们打开了一个 ServerChanel ,侦听本机的 9999 端口,并且新建了一个 Selector, 然后这个 ServerChanel 注册了这个 Selector ,并且指定了它感兴趣的状态类型是 OP_ACCEPT. 这样有什么效果呢?

注意红色那句,这句意思是selector要求serverChannel1状态为acceptable的时候把这个消息告诉selector。

效果就是:

当这个 ServerChanel 状态为 Acceptable 时, Selector 就会收到一个消息,这个消息当然就是一个 SelectionKey 对象。调用 Selector 的 selectedKeys ()方法,我们就能得到所有 Chanel 发送过来的消息。

因为 SelectionKey 包含 事件的状态,时间以及对应的 Chanel ,很自然的,我们遍历这个 Set, 根据 SelectionKey 的状态,就能在相应的 Chanel 做正确的操作。比如,能读的时候我们就读,能写的时候我们就写。

***讲讲 Server 端和 Client 编程的一般步骤:

对于 Client 来一般是这样的:

InetSocketAddress isa = new InetSocketAddress(host, port);   SocketChannel sc = null;   sc = SocketChannel.open();   sc.connect(isa);   sc.write(data);   …   Sc.read(buff);

构造一个 InetSocketAddress 对象 --> open --> connect --> write --> read

注意这里用的不是 No-Block 的方式,因为 client 如果没有得到 server 端的正确回应的话就采取下一步操作无疑是没有意义的。

Server 端:

selector = SelectorProvider.provider ().openSelector();   serverChannel = ServerSocketChannel.open ();   serverChannel .configureBlocking( false );   InetSocketAddress isa = new InetSocketAddress( "localhost" , 9999 );   serverChannel .socket().bind(isa);   serverChannel .register( selector , SelectionKey. OP_ACCEPT );

构造一个 Selector --> 打开一个 serverSocketChanel --> 设定 serverSocketChanel 为 no-block-->bind serverSocketChanel 到一个 host 和 port --> register Selector 并告知感兴趣的状态类型转换。

在 SelectionKey Set 上遍历操作:

while (true) {   selector.select();   Iterator selectedKeys = this.selector.selectedKeys().iterator();   while (selectedKeys.hasNext()) {   SelectionKey key = (SelectionKey) selectedKeys.next();   selectedKeys.remove();   if (!key.isValid()) {   continue;   }   if (key.isAcceptable()) {   accept(key);   } else if (key.isReadable()) {   read(key);   } else if (key.isWritable()) {   write(key);   }   }   }

在这个循环里面我们会根据 SelectionKey 的状态,采取不同的操作的。当连接被 accepted 时, 一个新的 chanel 会被生成,并且记录了 localAdrress 和 remoteAddress. 为进一步读写做准备。

accept 函数如下:

public void accept(SelectionKey key) throws IOException {   ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();  SocketChanel socketChannel1 = serverSocketChannel.accept();   socketChannel1.configureBlocking(false);   socketChannel1.register(selector, SelectionKey.OP_READ);   }

这里新的 Chanel 被构建,***同样会注册到 selector , 同时要求当这个 Chanel 为 Readable 时,一个 SelectionKey 被放入到 Selector 中。这样上面循环会用 read(key) 来处理这个 SelectionKey。

以上就是"Java NIO的知识点有哪些"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

状态 事件 数据 知识 适当 就是 时候 结果 面的 成功 时机 步骤 消息 篇文章 网络 知识点 马上 准备 不同 代码 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 瑰夏咖啡 工业互联网科技新基建 互联网 卓越科技 互联网科技公司怎么样 互联网与未来科技 百单互联网科技有限公司 互联网科技logo设计 联恩商钥互联网科技有限公司 哈尔滨秒房互联网科技有限公司 上海电发互联网科技有限公司 黑科技闪耀互联网之光 深圳育鹏互联网科技有限公司招聘 企晟互联网信息科技有限公司 翼展科技 首家互联网医院 四川慕妮娅互联网科技有限公司 保险科技服务互联网营销体系 恒生互联网科技业指数调整周期 扫呗互联网科技有限公司 广州智享互联网科技 易租星互联网科技有限公司 中智农互联网科技 广州淘业互联网络科技 深圳互联网络科技有限公司 华服互联网科技官网 中化能源互联网科技招聘 众安科技工业互联网合作 上海创道互联网络科技有限公司 世界互联网科技成果奖 恒生科技指数 中概互联网 银川新华互联网科技学校招聘
0