NIO学习资料
来源:互联网 发布:淘宝闹鬼的古着店 编辑:程序博客网 时间:2024/05/16 18:14
http://weixiaolu.iteye.com/blog/1479656
Java NIO提供了与标准IO不同的IO工作方式:
Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Selectors(选择器):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
IO面向流与NIO面向缓冲
Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
阻塞与非阻塞IO
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
NIO的channel
既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。通道可以异步地读写。
通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
这些是Java NIO中最重要的channel的实现:
FileChannel:从文件中读写数据。
DatagramChannel:能通过UDP读写网络中的数据。
SocketChannel:能通过TCP读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
以下是Java NIO里关键的Buffer实现:
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。
向Buffer中写数据
写数据到Buffer有两种方式:
从Channel写到Buffer。
通过Buffer的put()方法写到Buffer里。
从Channel写到Buffer的例子 :int bytesRead = inChannel.read(buf); //read intobuffer.
通过put方法写Buffer的例子: buf.put(127);
从Buffer中读取数据
从Buffer中读取数据有两种方式:
从Buffer读取数据到Channel。
使用get()方法从Buffer中读取数据。
从Buffer读取数据到Channel的例子: int bytesWritten =inChannel.write(buf);//read from buffer intochannel.
使用get()方法从Buffer中读取数据的例子:byte aByte = buf.get();
代码如下:
Name: Anna
Age: 25
Email: anna@mailserver.com
NIO的读取代码如下:
ByteBuffer buffer = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buffer);
注意第二行,从通道读取字节到ByteBuffer。当这个方法调用返回时,你不知道你所需的所有数据是否在缓冲区内。你所知道的是,该缓冲区包含一些字节,这使得处理有点困难。
假设第一次 read(buffer)调用后,读入缓冲区的数据只有半行,例如,“Name:An”,你能处理数据吗?显然不能,需要等待,直到整行数据读入缓存,在此之前,对数据的任何处理毫无意义。
所以,你怎么知道是否该缓冲区包含足够的数据可以处理呢?好了,你不知道。发现的方法只能查看缓冲区中的数据。其结果是,在你知道所有数据都在缓冲区里之前,你必须检查几次缓冲区的数据。这不仅效率低下,而且可以使程序设计方案杂乱不堪。
所以NIO可让您只使用一个(或几个)单线程管理多个通道(网络连接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂。
如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,实现NIO的服务器可能是一个优势。同样,如果你需要维持许多打开的连接到其他计算机上,如P2P网络中,使用一个单独的线程来管理你所有出站连接,可能是一个优势;如果你有少量的连接使用非常高的带宽,一次发送大量的数据,也许典型的IO服务器实现可能非常契合。
NIO的选择器(Selectors)
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。下面是单线程使用一个Selector处理3个channel的示例图:
(1)Selector的创建 :
通过调用Selector.open()方法创建一个Selector,Selector selector = Selector.open();
(2)向Selector注册通道 :
为了将Channel和Selector配合使用,必须将channel注册到selector上。
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);//与Selector一起使用时,Channel必须处于非阻塞模式下。
Selector监听Channel时对感兴趣事件做了四种常量值监听
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
可对多个同时监听:int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
(3)SelectionKey对象
当向Selector注册Channel时,register()方法会返回一个SelectionKey对象。这个对象包含几个属性:
interest集合:interest集合是你所选择的感兴趣的事件集合。
ready集合:ready 集合是通道已经准备就绪的操作的集合。
Channel:Channel channel= selectionKey.channel();
Selector:Selector selector = selectionKey.selector();
(4)通过Selector选择通道
(5)wakeUp()
某个线程调用select()方法后阻塞了,即使没有通道已经就绪,也有办法让其从select()方法返回。只要让其它线程在第一个线程调用select()方法的那个对象上调用Selector.wakeup()方法即可。阻塞在select()方法上的线程会立马返回。 如果有其它线程调用了wakeup()方法,但当前没有线程阻塞在select()方法上,下个调用select()方法的线程会立即“醒来(wake up)”。
(6)close()
用完Selector后调用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效。通道本身并不会关闭。
- java nio学习资料
- NIO学习资料
- Java NIO学习资料
- NIO资料整理
- NIO资料汇总
- java NIO 相关资料
- NIO学习
- Nio学习
- 学习NIO
- nio 学习
- NIO学习
- NIO学习
- 学习NIO
- NIO 学习
- NIO学习
- NIO学习
- NIO学习
- NIO学习
- C# 泛型学习总结(一)
- react学习笔记 item2 --- JSX
- HTML多出文本,用省略号解决的办法
- nginx-rtmp中next_publish与ngx_rtmp_publish
- EMS SQL Manager下载及中文配置
- NIO学习资料
- 使用Picasso下载图片时的错误
- 【NOIp模拟】【dp】俄罗斯方块
- Android 读取assets文件中的文件
- Java - 趣味题(2) --- 约瑟夫环
- 经典SQL练习题
- 微信号开通检测软件选择需谨慎
- ffmpeg混音以及音视频混合
- 组合数学第三次作业