基于NIO模型的Java Socket传统编程

基于NIO模型的Java Socket传统编程_第1张图片

     这张是2014年在拉卜楞寺拍摄的,僧人们下早课。红袍加身不可脱,这是其中一位僧人给我和基友担当向导时说的,他7岁从青海来学习佛法,因为家里还有一个哥哥,两个男孩的话弟弟会被送去佛学院出家,所以他被送出来了,现在已经26了,将来可以选择回家乡附近的寺庙工作,也可以留在这所佛学院或寺里继续工作,其他记不太住了,只记得当时我用的iphone4,他用的iphone5s。

基于NIO模型的Java Socket传统编程_第2张图片

基于NIO模型的Java Socket传统编程_第3张图片

   

王皓的GitHub:https://github.com/TenaciousDWang

 

      在上一篇文章中,我们说的是基于BIO模型下的Java Socket传统编程,其中我们提到了很多关于BIO的弊病。

 

      现在,我们来说一下在Java中基于NIO模型的Socket编程,NIO在有的文章中叫做Non-block Input&Output Model,也有文章叫做New Input/Output Model,总之就是为了优化BIO中的问题而提出的新的解决方案。

 

基于NIO模型的Java Socket传统编程_第4张图片

      这里引用一下《Netty in action》里面的插图,我们看到上图就是BIO模型下一个线程管理一个Socket。

 

基于NIO模型的Java Socket传统编程_第5张图片

       NIO模型中,把一堆线程都交给一个Selector来管理,使用一个单一线程便可以处理多个并发连接。

        

      我们直接举一个现实中通俗的例子来讲,在一个商场内里,顾客需要导购员介绍商品或提供服务,现在有100个顾客,有两种方案可以解决这个问题:

 

     1.每个顾客配一个导购员。每个导购员跟着随时应对顾客提出的问题,这就是传统IO模型,一个连接对应一个线程。

 

      2.商场里面只放5个导购员。每个导购员应对20个顾客,一个导购员一直轮训这20个顾客,有需求就来解决,这就是 NIO 模型,一堆顾客都注册到同一个导购员,对应的就是一堆连接都注册到一个线程,然后批量轮询,一个线程可以管理一批连接,相对于 IO 模型中一个线程对应一条连接,这就是 NIO 模型解决线程资源受限的方案,线程资源消耗大幅减少。

  

     上面的例子非常简洁明了,BIO模型不适用于socket连接数巨大的情况。在NIO模型下的导购员就是其selector的概念,一个线程管理多条连接,大大减少了对资源的浪费,同时NIO模型中线程数量的大量减少,提升了线程切换的效率,也就是提高的通信效率。

 

      传统IO的读写是使用流来读写,需要自己来缓存数据,NIO采用了Buffer读写,我们只需要移动指针即可。

 

      虽然上述说了一大堆NIO模型下Socket编程的好处,但是在现在的网上和各类书籍中却不建议使用原生java的nio包进行编程,大概总结原因如下:

 

  1. NIO编程中需要了解很多的概念,且编程复杂,编程方式不友好。
  2. NIO编程中你需要自己实现一个线程模型,很多工具类都要你自己实现比如拆包等。
  3. NIO底层由epoll实现,该实现饱受诟病的空轮询bug会导致cpu飙升100%到现在还存在这个BUG。
  4. NIO编程中代码量,业务逻辑非常庞大后,自己写的NIO很容易出现各类BUG,维护成本较高。

 

      这里只讲NIO模型下Socket编程的原理,不再列出举例代码,网上很多关于NIO的资料感兴趣可以查阅。

 

        尽管已经有许多直接使用Java NIO API 的应用程序被构建了,但是要做到如此正确和安全并不容易。特别是,在高负载下可靠和高效地处理和调度I/O 操作是一项繁琐而且容易出错的任务,

最好留给高性能的网络编程专家——Netty。

 

      Netty是Java网络编程领域的卓越框架。

     最后推荐一本书:《Netty in action》。

 

你可能感兴趣的:(Netty,Netty,IM实战)