Java NIO:NIO概述html
在上一篇博文中讲述了几种IO模型,如今咱们开始进入Java NIO编程主题。NIO是Java 4里面提供的新的API,目的是用来解决传统IO的问题。本文下面分别从Java NIO的几个基础概念介绍起。java
如下是本文的目录大纲:编程
一.NIO中的几个基础概念数组
二.Channel网络
三.Buffer多线程
四.Selector函数
如有不正之处,请多多谅解并欢迎批评指正。spa
请尊重做者劳动成果,转载请标明原文连接:.net
http://www.cnblogs.com/dolphin0520/p/3919162.html线程
在NIO中有几个比较关键的概念:Channel(通道),Buffer(缓冲区),Selector(选择器)。
首先从Channel提及吧,通道,顾名思义,就是通向什么的道路,为某个提供了渠道。在传统IO中,咱们要读取一个文件中的内容,一般是像下面这样读取的:
public class Test { public static void main(String[] args) throws IOException { File file = new File("data.txt"); InputStream inputStream = new FileInputStream(file); byte[] bytes = new byte[1024]; inputStream.read(bytes); inputStream.close(); } }
这里的InputStream实际上就是为读取文件提供一个通道的。
所以能够将NIO 中的Channel同传统IO中的Stream来类比,可是要注意,传统IO中,Stream是单向的,好比InputStream只能进行读取操做,OutputStream只能进行写操做。而Channel是双向的,既可用来进行读操做,又可用来进行写操做。
Buffer(缓冲区),是NIO中很是重要的一个东西,在NIO中全部数据的读和写都离不开Buffer。好比上面的一段代码中,读取的数据时放在byte数组当中,而在NIO中,读取的数据只能放在Buffer中。一样地,写入数据也是先写入到Buffer中。
下面介绍一下NIO中最核心的一个东西:Selector。能够说它是NIO中最关键的一个部分,Selector的做用就是用来轮询每一个注册的Channel,一旦发现Channel有注册的事件发生,便获取事件而后进行处理。
好比看下面的这个例子:
用单线程处理一个Selector,而后经过Selector.select()方法来获取到达事件,在获取了到达事件以后,就能够逐个地对这些事件进行响应处理。
在前面已经提到,Channel和传统IO中的Stream很类似。虽然很类似,可是有很大的区别,主要区别为:通道是双向的,经过一个Channel既能够进行读,也能够进行写;而Stream只能进行单向操做,经过一个Stream只能进行读或者写;
如下是经常使用的几种通道:
经过使用FileChannel能够从文件读或者向文件写入数据;经过SocketChannel,以TCP来向网络链接的两端读写数据;经过ServerSocketChanel可以监听客户端发起的TCP链接,并为每一个TCP链接建立一个新的SocketChannel来进行数据读写;经过DatagramChannel,以UDP协议来向网络链接的两端读写数据。
下面给出经过FileChannel来向文件中写入数据的一个例子:
public class Test { public static void main(String[] args) throws IOException { File file = new File("data.txt"); FileOutputStream outputStream = new FileOutputStream(file); FileChannel channel = outputStream.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); String string = "java nio"; buffer.put(string.getBytes()); buffer.flip(); //此处必需要调用buffer的flip方法 channel.write(buffer); channel.close(); outputStream.close(); } }
经过上面的程序会向工程目录下的data.txt文件写入字符串"java nio",注意在调用channel的write方法以前必须调用buffer的flip方法,不然没法正确写入内容,至于具体缘由将在下篇博文中具体讲述Buffer的用法时阐述。
Buffer,故名思意,缓冲区,其实是一个容器,是一个连续数组。Channel提供从文件、网络读取数据的渠道,可是读取或写入的数据都必须经由Buffer。具体看下面这张图就理解了:
上面的图描述了从一个客户端向服务端发送数据,而后服务端接收数据的过程。客户端发送数据时,必须先将数据存入Buffer中,而后将Buffer中的内容写入通道。服务端这边接收数据必须经过Channel将数据读入到Buffer中,而后再从Buffer中取出数据来处理。
在NIO中,Buffer是一个顶层父类,它是一个抽象类,经常使用的Buffer的子类有:
若是是对于文件读写,上面几种Buffer均可能会用到。可是对于网络读写来讲,用的最多的是ByteBuffer。
关于Buffer的具体使用以及它的limit、posiion和capacity这几个属性的理解在下一篇文章中讲述。
Selector类是NIO的核心类,Selector可以检测多个注册的通道上是否有事件发生,若是有事件发生,便获取事件而后针对每一个事件进行相应的响应处理。这样一来,只是用一个单线程就能够管理多个通道,也就是管理多个链接。这样使得只有在链接真正有读写事件发生时,才会调用函数来进行读写,就大大地减小了系统开销,而且没必要为每一个链接都建立一个线程,不用去维护多个线程,而且避免了多线程之间的上下文切换致使的开销。
与Selector有关的一个关键类是SelectionKey,一个SelectionKey表示一个到达的事件,这2个类构成了服务端处理业务的关键逻辑。
关于Selector类的具体使用将在后续文章中阐述。
参考资料:
http://blog.csdn.net/wuxianglong/article/details/6604817
http://www.360doc.com/content/12/0515/11/1542811_211144310.shtml
http://www.iteye.com/topic/834447