如果有人再问你 Java IO,把这篇文章砸他头上( 六 )


当然,客户端也不仅仅只限制于 IO 的写法,还可以使用SocketChannel来操作客户端,程序如下:

如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
一样的,先启动服务端,再启动客户端,客户端运行结果如下:
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
从操作上可以看到,NIO 的操作比传统的 IO 操作要复杂的多!
Selector 被称为选择器 ,当然你也可以翻译为多路复用器  。它是 Java NIO 核心组件中的一个,用于检查一个或多个 Channel(通道)的状态是否处于连接就绪、接受就绪、可读就绪、可写就绪 。
如此可以实现单线程管理多个 channels,也就是可以管理多个网络连接 。
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
使用 Selector 的好处在于: 相比传统方式使用多个线程来管理 IO,Selector 使用了更少的线程就可以处理通道了,并且实现网络高效传输!
虽然 java 中的 nio 传输比较快,为什么大家都不愿意用 JDK 原生 NIO 进行开发呢?
从上面的代码中大家都可以看出来,除了编程复杂、编程模型难之外,还有几个让人诟病的问题:
  • JDK 的 NIO 底层由 epoll 实现,该实现饱受诟病的空轮询 bug 会导致 cpu 飙升 100%!
  • 项目庞大之后,自行实现的 NIO 很容易出现各类 bug,维护成本较高!
但是,google 的 Netty 框架的出现,很大程度上改善了 JDK 原生 NIO 所存在的一些让人难以忍受的问题,关于 Netty 框架,会在后期的文章里进行介绍 。
6.4.4、AIO最后就是 AIO 了,全称 Asynchronous I/O,可以理解为异步 IO,也被称为 NIO 2,在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型,也就是我们现在所说的 AIO 。
异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作 。
客户端,程序示例:
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
服务端,程序示例:
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
同样的,先启动服务端程序,再启动客户端程序,看看运行结果!
服务端,运行结果如下:
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
客户端端,运行结果如下:
如果有人再问你 Java IO,把这篇文章砸他头上

文章插图
 
这种组合方式用起来比较复杂,只有在一些非常复杂的分布式情况下使用,像集群之间的消息同步机制一般用这种 I/O 组合方式 。如 Cassandra 的 Gossip 通信机制就是采用异步非阻塞的方式 。
Netty 之前也尝试使用过 AIO,不过又放弃了!
七、总结本文阐述的内容较多,从 Java 基本 I/O 类库结构开始说起,主要介绍了 IO 的传输格式和传输方式,以及磁盘 I/O 和网络 I/O 的基本工作方式 。
【如果有人再问你 Java IO,把这篇文章砸他头上】本篇文章主要对 Java 的 IO 体系以及计算机部分网络基础知识做了些简单的介绍,其实每一个模块涉及到的知识都非常非常多,在后期的文章中,会对各个模块进行详细的介绍,如果有理解不到的位置,欢迎指出!


推荐阅读