NIO与IO
待续。。。
该文章部分摘自:http://tutorials.jenkov.com/java-nio/index.html
一、I/O简介
I/O(英语:Input/Output),即输入/输出, 指的是计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。
IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。
Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。
二、NIO
1、概念:
NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础。
2、NIO与I/O区别
NIO 与原来的 I/O 有同样的作用和目的,但是它使用不同的方式? 块 I/O。
原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
3、NIO概述
NIO:通道和缓冲区
在标准IO API中,使用字节流和字符流。 而在NIO中,使用的是通道和缓冲区。 数据总是从通道读入缓冲区,或从缓冲区写入通道。
NIO: 非阻塞IO
线程可以要求通道将数据读入缓冲区。 当通道将数据读入缓冲区时,线程可以执行其他操作。 一旦数据被读入缓冲区,线程就可以继续处理它。 将数据写入通道也是如此。
Java NIO: Selectors
选择器是一个可以监视多个事件通道的对象(例如:连接打开,数据到达等)。 因此,单个线程可以监视多个通道的数据。
4、Java NIO Channel
通道类似于流,但是有一些差异:
1) 通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。
2) 可以异步读取和写入通道。
3) 通道将数据读入缓冲区,缓冲区将数据写入通道
Channel Implementations
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
FileChannel从文件读取数据和读取数据到文件。
DatagramChannel可以通过UDP在网络上读写数据。
SocketChannel可以通过TCP在网络上读写数据。
ServerSocketChannel允许您监听传入的TCP连接,就像Web服务器一样。 对于每个传入连接,都会创建一个SocketChannel。
4、Java NIO Buffer
在与NIO通道交互时使用Java NIO缓冲区。 如您所知,数据从通道读入缓冲区,并从缓冲区写入通道。
缓冲区本质上是一个可以写入数据然后可以再次读取的内存块。 此内存块包含在NIO Buffer对象中,该对象提供了一组方法,可以轻松地使用内存块。
5、Java NIO Selector
Java NIO Selector是一个可以检查一个或多个Java NIO Channel实例的组件,能确定哪些通道可以用于例如 阅读或写作。 这样,单个线程可以管理多个通道,从而管理多个网络连接。
Java NIO:一个Thread使用一个Selector来处理3个Channel
使用步骤:
(1)创建一个Selector:
Selector selector = Selector.open();
(2)要使用带选择器的通道,必须使用选择器注册通道。
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
通道必须处于非阻塞模式才能与选择器一起使用。 这意味着您无法将FileChannel与Selector一起使用,因为FileChannel是无法切换到非阻塞模式的。而Socket channels是可以正常工作。
注意register()方法的第二个参数。 这是一个“兴趣集”,意味着您有兴趣在频道中通过选择器收听哪些事件。 您可以收听四种不同的活动:
- Connect
- Accept
- Read
- Write
这四个事件由四个SelectionKey常量表示:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
如果您对多个事件感兴趣,或者将常量放在一起,如下所示:
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
SelectionKey
Java NIO SocketChannel
打开一个SocketChannel:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));