Java NIO和IO之间第一个区别是,IO是面向流的,NIO是面向缓冲区的。Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
另外,Java IO的各种流是阻塞的,而Java NIO是非阻塞的。IO是当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 而Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
而且,Java IO: 一个典型的IO服务器设计- 一个连接通过一个线程处理,而NIO可让您只使用一个单线程管理多个通道(网络连接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂。
使用方式:
关于IO:
ByteBuffer buffer = ByteBuffer.allocate(48);
String str = reader.readLine();
关于NIO:
ByteBuffer buffer = ByteBuffer.allocate(48);
int bytes = inChannel.read(buffer);
while(! bufferFull(bytes) ) {
bytes = inChannel.read(buffer);
}
Java NIO 由Channels、Buffers、Selectors三个主要核心部分组成
Channel的几种类型:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
FileChannel 从文件中读写数据。
DatagramChannel 能通过UDP读写网络中的数据。
SocketChannel 能通过TCP读写网络中的数据。
ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
Buffer的几种类型:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
- MappedByteBuffer
使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
通过调用Selector.open()方法创建一个Selector
Selector selector = Selector.open();
为了将Channel和Selector配合使用,必须将channel注册到selector上。通过SelectableChannel.register()方法来实现
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
与Selector一起使用时,Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(serverPort));
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(serverPort));
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(serverPort));
while(true){
SocketChannel socketChannel =serverSocketChannel.accept();
}
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel传输到另外一个channel。(调用transferFrom()方法和transferTo(),都是FileChannel的方法)