一、JAVA的NIO和IO
1、NIO:面向缓冲区(buffer)(分为非阻塞模式IO和阻塞模式IO)组成部分:Channels管道,Buffers缓冲区,Selectors选择器
2、IO:面向流(Stream)(阻塞的IO)
面向流:当一个线程调用read() 或 write()时,线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。流就像一根水管从操作系统的缓存中读取数据,而且只能顺序从流中读取数据,如果需要跳过一些字节或者再读取已经读过的字节,你必须将从流中读取的数据先缓存起来。
面向缓冲区:数据是先被读/写到buffer中的,根据需要你可以控制读取什么位置的数据。这在处理的过程中给用户多了一些灵活性,然而,你需要额外做的工作是检查你需要的数据是否已经全部到了buffer中,如果你还需要保证当有更多的数据进入buffer中时,buffer中未处理的数据不会被覆盖就行。
注:所有的JAVA的IO流都是阻塞的,JAVA NIO的阻塞模式NIO除了使用buffer存储数据以外和JAVA IO基本没区别。
JAVA NIO的非阻塞模式允许一条线程从管道channel中读取数据,通过返回值来判断buffer中是否有数据,如果没有数据,NIO不糊阻塞,不阻塞这个线程就意味着这个线程可以去做其他的事情,过一段时间再回来判断有没有数据。
JAVA NIO的写入也是如此,一个线程将buffer中的数据写入管道channel中,它不会等待数据全部写完才会返回,而是调用完write()方法就会继续向下执行。
二、JAVA NIO的Selectors(选择器)
选择器(Selectors)允许一个线程去监控多个channels的输入,也就是说可以在一个selector上注册多个管道channel,然后通过调用selector的select()方法判断是否有新的连接进来或者已经在selector上注册的channel是否有数据进入。selector的机制让一个线程挂你多个管道变简单。
//创建选择器 Selector selector=Selector.open(); //注册通道Channel //与选择器Selector一块使用的时候,Channel必须是非阻塞模式。 channel.configureBlocking(false); //第二个参数:Selector监听channel时所作的事件 //SelectionKey.OP_CONNECT/SelectionKey.OP_ACCEPT/SelectionKey.OP_READ/SelectionKey.OP_WRITE SelectionKey key=channel.register(selector,SelectionKey.OP_READ); //SelectionKey包含了interest集合,ready集合,Channel,Selector的对象。 int interestSet=key.interestOps();
总结:NIO允许用一个单独的线程或者几个线程管理很多个管道(channels),只是程序的处理会比JAVA IO更加复杂。
一般来说,你如果只有少量的连接但是每个连接都会占有很高的带宽,同时发送很多的数据,传统的JAVA IO会更好。
一般来说,如果你需要同时管理成千上万的连接,但是每个连接只是发送少量的数据,选择JAVA NIO会更好,比如一个聊天服务器,使用NIO更好。
三、JAVA NIO的Channel管道
主要包括了UDP,TCP,SOCKET等网络IO,以及File文件IO
FileChannel DatagramChannel SocketChannel ServlerSocketChannel
读取数据:
int bytesRead=inChannel.read(buf);
写入数据:
int bytesWrite=inChannel.write(buf);
/*SocketChannel通道*/ //建立SocketChannel通道 SocketChannel socketChannel=SocketChannel.open(); socketChannel.connect(new IntSocketAddress("LOL.exe",10)); //读取数据 ByteBuffer buf=ByteBuffer.allocate(20); int bytesRead=socketChannel.read(buf); //写入数据 String data="HelloWorld"+System.currentTimeMills(); ByteBuffer buf=ByteBuffer.allocate(20); buf.clear();//清空整个缓冲区。 buf.put(data.getBytes());//写入数据 buf.flip();//将Buffer从写入模式切换到读取模式 while(buf.hasRemaining()){ socketChannel.write(buf); }
四、JAVA NIO的Buffer缓冲区
主要包括了读基本数据类型的实现Buffer
ByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer