nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接。很多同学提起nio都能说起一二,但是细究其背后的原理、思想往往就开始背书,说来说去都是那么几句,其中不少人并不见的真的很理解。本人之前就属于此类,看了很多书和博客,但是大多数都只是讲了三件套和怎么使用,很少会很细致的讲背后的思想,那本次我们就来扒一扒吧。
很多博客描述nio都是这么说的:基于Reactor模式实现的多路非阻塞高性能的网络IO。那么我们就从这个定义来分析,其中两个关键点:多路非阻塞和Reactor模式。(本来想把高性能也算进去,但是后来想想这个应该算前两者的结果)下边我们来分别搞懂这两块。
NIO的细节就不多讲了,这里只介绍下三件套:
再来看个简图吧:
从《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. MultiplexerTimerServer implements Runnable { private Selector selector; private ServerSocketChannel servChannel; 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做对应处理 } }
View Code 六、最后一点啰嗦