Java NIO 入门

发布时间:2019-11-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Java NIO 入门脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

关于多路复用

很多人用过InputStreamOutputStream接口,用来操作文件Socket等等 IO 操作。
如果是简单的,速度较快的 IO 操作,我们用Stream类的接口,依然可以风生水起。
如果你要使用非阻塞的 IO 的话,他们可能就满足不了你了。

熟悉操作系统的人会知道,操作非阻塞 IO 无非几种多路复用:

@H_777_19@
  • select

  • poll

  • epoll

  • kqueue

  • IOCP

  • 这里的复用模型有几个是操作系统相关的——也就是说,并不是所有的操作系统都可以用,典型的就是IOCPWindows的"专利",kqueueBSD的"专利"(比如macOS)。

    那么 java 作为一门跨平台的语言解决方案,是如何在虚拟机上使用 non-blocking IO 的呢?
    具体的实现我们可以不管,它使用了SelectorAPI,调用方式非常类似select

    Channel & ByteBuffer vs Stream

    nio中,不再使用Stream APISocket进行交互,而是使用ChannelByteBuffer进行交互,
    Channel负责管道的工作,ByteBuffer负责缓存的工作。

    原先InputStreamOutputStream的工作就由Channel做掉了,如果这个Channel支持Select模型的话,它就是SelectableChannel的子类。
    那么,在消息循环的模型中,首先要建立循环,像我们的LooPEr.loop()一样,我们先用Selector.open()新建一个Selector

    Selector eventSelector = Selector.open();  // 设置这个 channel 是非阻塞的 socketChannel.configureBlocking(false);  // 注册到 selector 里,并设置好关心的事件 socketSelectionKey = socketChannel.register(eventSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

    Selector

    接下来调用 eventSelector.select() 阻塞,就能在你关心的事件到来的时候,阻塞就会被唤醒,处理事件。

    sample:

    while (connected) {     eventSelector.select();     Set<SelectionKey> keys = eventSelector.selectedKeys();     Iterator<SelectionKey> iterator = keys.iterator();     while (iterator.hasNext()) {         SelectionKey key = iterator.next();         if (key.isReadable()) {             // 当 socket 可读             internalOnRead((ReadableByteChannel) key.channel());         }          if (key.isWritable()) {             // 当 socket 可写             internalOnWrite((WritableByteChannel) key.channel());         }         iterator.remove();     } }

    总结

    nio 对于客户端的优势几乎没有,但是可以让代码更好管理; 如果这时候你使用的是ServerSocket,好处就立马体现了,因为你的业务需求很可能是这样:

    1. master 线程,开启 accept.

    2. 如果有客户接入,开启一个 worker,用来服务 client。

    3. 服务完后,保持或者关闭这个连接。

    (这个业务模型类似apache httpd)这样的业务模型可能导致过多的线程开销,使得并发量并不高。

    那么,老生常谈的event-driven的模型在java中,就差不多是这样的逻辑:

    1. master 线程,开启 selector, 并为 ServerSocket 注册 accept, read, write 等事件。

    2. 客户接入,为 client socket 注册 read, write 事件,依旧在该线程里面进行循环。

    3. 当 event trigger 的时候,处理相关业务逻辑。

    第二个模型只启动了一个线程,所有的IO操作都在 OS 里面完成了,用户空间内的资消耗大大降低,这也是我们把 Server 端的 IO 改成 nio 的优势。

    脚本宝典总结

    以上是脚本宝典为你收集整理的Java NIO 入门全部内容,希望文章能够帮你解决Java NIO 入门所遇到的问题。

    如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。