nio是java的IO框架里边十分重要的一部份内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络链接。不少同窗提起nio都能提及一二,可是细究其背后的原理、思想每每就开始背书,说来讲去都是那么几句,其中很多人并不见的真的很理解。本人以前就属于此类,看了不少书和博客,可是大多数都只是讲了三件套和怎么使用,不多会很细致的讲背后的思想,那本次咱们就来扒一扒吧。
不少博客描述nio都是这么说的:基于Reactor模式实现的多路非阻塞高性能的网络IO。那么咱们就从这个定义来分析,其中两个关键点:多路非阻塞和Reactor模式。(原本想把高性能也算进去,可是后来想一想这个应该算前二者的结果)下边咱们来分别搞懂这两块。html
多路非阻塞其实准确的名字叫作IO多路复用模型,其是linux五种网络模型之一,也是当前网络编程最常使用的模型之一。至于详细的介绍请参考博客:高性能IO模型浅析(这个里边只给出了4中,没有信号驱动IO,但讲的很赞,特别是图),这里仅做简要介绍和对比:java
对比以上五种模型能够知道,IO复用模型从效率和实现成本综合而言目前是比较好的选择,这就是java基于该模型实现nio的根本缘由。上边提到了IO复用模型的实现思想,其实这种思想在其余语言中早已实现(如C++中听说流弊哄哄超10w行代码的ACE,自适配通讯环境,就采用了该模型),而且提出了一个叫Reactor的设计模式。react
Reactor模式,翻译过来叫作反引器模式,其目的是在事件驱动的应用中,将一个请求的可以分离而且调度给应用程序。我相信大多数人都没看明白前一句的意思(书仍是要背的),说白了就是对于一个请求的多个事件(如链接、读写等),通过这种模式的处理,可以区分出来,而且分别交给对应的处理模块处理。废话很少说,来看下一个简图:
linux
再来看个简图吧: 编程
基本上和Reactor能对应上,少了个dispatcher,这是因为jdk自己提供的nio比较基本,dispatcher通常都由咱们本身实现,而在我理解中,mina、netty这些框架很重要的一方面也是提供了该部分的实现。
设计模式
从《netty权威指南》上抄了个例子以及配图,并且代码没有客户端的,你们能够瞄一眼吧(为何没有?由于已经快一点了,我不想写了......):
服务器端时序图:数组
客户端时序图: 服务器
服务器端代码:
网络
package com.gj.netty.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.util.Iterator; import java.util.Set; /** * Created by guojing on 2015/6/7. */ public class MultiplexerTimerServer implements Runnable { private Selector selector; private ServerSocketChannel servChannel; private volatile boolean stop; public MultiplexerTimerServer(int port) { try { selector = Selector.open(); //新建多路复用selector servChannel = ServerSocketChannel.open(); //新建channel servChannel.configureBlocking(false); //设置非阻塞 servChannel.socket().bind(new InetSocketAddress(port),1024); //端口、块大小 servChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("TimeServer is start, port:" + port); } catch (IOException e) { e.printStackTrace(); } } public void run() { while (!stop){ try { selector.select(1000); Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> ketIt = keys.iterator(); SelectionKey key = null; while (ketIt.hasNext()){ key = ketIt.next(); ketIt.remove(); //处理对应key事件 handler(key); } } catch (IOException e) { e.printStackTrace(); } } } private void handler(SelectionKey key){ //根据key去除channel作对应处理 } }
我想若是这会儿还有人记得标题必定会骂我了,丫的十分钟个屁啊,认真看完至少待半个小时。这个我只能说若是你以前已经理解了,那么画个10分钟瞟一眼无所谓的,若是之前没理解,若是本文能让你有了更好的理解,那么花多少时间更无所谓了,要知道懂了java的nio是量的积累,了解了其背后的思想和原理是质的积累。并且,我明明计划半小时写完的,这会已经2个多小时过去了......框架