Java之NIO

java.nio全称java non-blocking IO(实际上是 new io),是指jdk1.4 及以上版本里提供的新api(New IO) ,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。
NIO是为了弥补IO操作的不足而诞生的,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。

  • Selector:选择器用于监听多个通道的事件。使用传统的阻塞IO时我们可以方便的知道什么时候可以进行读写,而使用非阻塞通道,我们需要一些方法来知道什么时候通道准备好了,选择器正是为这个需要而诞生的。

NIO和IO的区别

  • IO是面向流的,NIO是面向块(缓冲区)的。
    • IO面向流的操作一次一个字节地处理数据。导致了数据的读取和写入效率不佳;
    • NIO面向块的操作。按块处理数据比按(流式的)字节处理数据要快得多,同时数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。
  • IO是阻塞的,NIO是非阻塞的。
    • 对于传统的IO,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。
    • 而对于NIO,使用一个线程发送读取数据请求,没有得到响应之前,线程是空闲的,此时线程可以去执行别的任务,而不是像IO中那样只能等待响应完成。

NIO和IO适用场景

  • NIO是为弥补传统IO的不足而诞生的,但是NIO也有缺点,因为NIO是面向缓冲区的操作,每一次的数据处理都是对缓冲区进行的,那么就会有一个问题,在数据处理之前必须要判断缓冲区的数据是否完整或者已经读取完毕,如果没有,假设数据只读取了一部分,那么对不完整的数据处理没有任何意义。所以每次数据处理之前都要检测缓冲区数据。
  • 如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,这时候用NIO处理数据可能是个很好的选择。
  • 而如果只有少量的连接,而这些连接每次要发送大量的数据,这时候传统的IO更合适。
  • 使用哪种处理数据,需要在数据的响应等待时间和检查缓冲区数据的时间上作比较来权衡选择。

Channel

概述

  • 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
  • 通道可以异步地读写。
  • 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。

Channel的实现

  • FileChannel:通过文件读写数据。只能通过getChannel()方法来创建对象,不能直接来创建对象。如:
FileInputStream fis = new FileInputStream("D:\\file-read.txt"); //  IOFile流
ReadableByteChannel rbc = fis.getChannel(); // 转换为Channel对象
  • DatagramChannel:通过UDP(用户数据报协议)读写网络中的数据。使用工厂方法来创建新对象。如:
DatagramChannel ch = DatagramChannel.open(); // 打开
DatagramChannel ch = DatagramChannel.close(); // 关闭
  • SocketChannel:通过TCP(传输控制协议)读写网络中的数据。使用工厂方法来创建新对象。如
// 打开
SocketChannel ch = SocketChannel.open();  
ch.connect(new InetSocketAddress("somehost", someport));

// 关闭
SocketChannel ch = SocketChannel.close();  
ch.connect(new InetSocketAddress("somehost", someport));
  • ServerSocketChannel:可以监听TCP连接,像web服务器一样。对每一个连接都会创建一个SocketChannel。如:
// 打开
ServerSocketChannel ch = ServerSocketChannel.open();  
ch.socket().bind (new InetSocketAddress (somelocalport));

// 关闭
ServerSocketChannel ch = ServerSocketChannel.close();  
ch.socket().bind (new InetSocketAddress (somelocalport));

Channel接口

public interface Channel extends Closeable {
	public boolean isOpen(); // 检查通道是否开启
    public void close() throws IOException; // 关闭通道
}

猜你喜欢

转载自blog.csdn.net/java852987/article/details/82763352
今日推荐