转载请标明:http://blog.geekcome.com/archives/261
Java NIO核心组件:
- channels
- Buffers
- Selectors
虽然NIO还有其他的组件,上面的三个是核心。
Channel
基本上,所以的IO在NIO中都是从一个Channel开始。Channel有点像流(Stream),数据可以从Channel读取到Buufer,也可以从Buffer写到Channel。Channel有下面的几种类型:
- FileChannel(文件IO)
- DatagramChannel(UDP数据报IO)
- SocketChannel(TCP数据报IO)
- ServerSocketChannel(监听新进来的TCP链接)
Channel和流的区别:
- Channel可以是双向的,流一般是单向的
- Channel可以异步的读写
- Channel总是需要Buffuer来读写数据
ServerSocketChannel:
1 |
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); |
2 |
serverSocketChannel.socket().bind( new InetSocketAddress( 9999 ));
|
4 |
SocketChannel socketChannel =
|
5 |
serverSocketChannel.accept();
|
ServerSocketChannel:
1 |
socketChannel.configureBlocking( false );
|
4 |
while (! socketChannel.finishConnect() ){
|
Buffer
NIO中Buffer的类型:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
- Mappeddyteuffer
这些Buffer覆盖了你能通过IO发送的数据基本类型,顾名思义。
使用Buffer的四个步骤:
- 写入数据到Buffer
- 调用flip()函数
- 从Buffer中读取数据
- 调用clear()函数
01 |
RandomAccessFile aFile = new RandomAccessFile( "/home/yan/pci1" , "rw" );
|
02 |
FileChannel channel = aFile.getChannel();
|
04 |
ByteBuffer buf = ByteBuffer.allocate( 20 );
|
06 |
int res = channel.read(buf);
|
09 |
while (buf.hasRemaining()){
|
10 |
System.out.println(( char )buf.getChar());
|
14 |
res = channel.read(buf);
|
Buffer还支持多个Buffer组成缓冲数组,对其进程读写操作。
Selector
Selector允许单线程处理多个Channel(一个Channel就是一个连接),如果每个连接的流量都很小,使用Selector就会很方便,如上图所示。而不用每个Channel来新建一个线程处理。
要使用Selector,首先要进程注册,想selector注册Channel,然后调用selector的select方法。这个方法会阻塞到某个注册的事件就绪,一旦这个方法返回,线程就可以处理这些事件。
创建Selector
调用Selector.open()方法来创建一个Selector:
1 |
Selector selector = Selector.open() |
像Selector注册通道:
1 |
channel.configureBloacking( false );
|
2 |
SelectionKey key = channel.register(selector,SeletionKey.OP_READ); |
SelectionKey
SelectionKey对象中含有如下属性:
- interest集合(使用&操作SelectionKey.OP_ACCEPT和key.interestOps())
- ready集合(key.readyOps(),可以使用&操作检测该集合,也可以使用is方法)
- Channel(key.channel())
- Selector(key.selector())
- 附加对象(key.attach(obj) Object obj = key.attachment())
selector通道选择
- int select()//阻塞
- int select(long timeout)//超时之前阻塞
- int selectNow()//不阻塞
selectedKeys()
一单调用select方法并且返回了,说明有一个或多个通道就绪了,然后通过该方法选择已经就绪的集合,然后遍历这些集合对每个通道进行处理。
01 |
Set selectedKeys = selector.selectedKeys(); |
02 |
Iterator keyIterator = selectedKeys.iterator(); |
03 |
while (keyIterator.hasNext()) {
|
04 |
SelectionKey key = keyIterator.next();
|
05 |
if (key.isAcceptable()) {
|
07 |
} else if (key.isConnectable()) {
|
09 |
} else if (key.isReadable()) {
|
11 |
} else if (key.isWritable()) {
|
参考文章:http://tutorials.jenkov.com/java-nio/overview.html
非阻塞I/O–Java NIO教程,布布扣,bubuko.com
非阻塞I/O–Java NIO教程