IO和NIO
Java BIO java blocking IO 阻塞式IO
Java NIO java non-blocking IO 非阻塞IO
标准阻塞IO
字节流:以 8 位(即 1 byte,8 bit)作为一个数据单元,数据流中最小的数据单元是字节。
字符流:以 16 位(即 1 char,2 byte,16 bit)作为一个数据单元,数据流中最小的数据单元是字符, Java 中的字符是 Unicode 编码,一个字符占用两个字节。 IO最基本的是 4
个抽象类:InputStream、OutputStream、Reader、Writer。最基本的方法也就是一个读 read() 方法、一个写
write() 方法。
文件流(File):从磁盘文件中输入输出或读写数据
- FileInputStream、FileOutputStream
- FileReader、FileWriter
数组流(byte[]、char[]): 从数组中输入输出或读写数据
- ByteArrayInputStream、ByteArrayOutputStream
- CharArrayReader、CharArrayWriter
管道流:从线程共用的管道中读写数据。
- PipedInputStream、PipedOutputStream
- PipedReader、PipedWriter
数据流:将基础类型数据以流的形式输入文件、输出到程序
- DataInputStream、DataOutputStream
缓冲流:二次处理包装流,在给普通流增加缓冲功能
- BufferedInputStream、BufferedOutputStream
- BufferedReader、BufferedWriter
转换流:二次处理包装流,字节流和字符流相互转换
- InputStreamReader、OutputStreWriter
打印流:控制台的输入输出 System.io 和 System.out
- PrintStream、PrintWriter
对象流:主要用于对象序列化和反序列化
- ObjectInputStream、ObjectOutputStream
非阻塞新IO
Buffer(缓冲)
- Buffer是一个对象,它用来存放即将发送的数据和即将到来的数据。Buffer实际上就是一个数组,通常是字节数组,但是这个数组提供了访问数据的读写等操作属性,如位置,容量,上限等概念。
- 在NIO中,Buffer是一个抽象类,常用的子类有、对于文件读写的:ByteBuffer、IntBuffer、ShortBuffer、CharBuffer、LongBuffer、DoubleBuffer、FloatBuffer、ShortBuffer。对于网络读写来说,用的最多的是ByteBuffer。
向Buffer中读写数据有两种方式:
从Channel读写到Buffer
**读**: int bytesWritten = inChannel.write(buf);
**写**:int bytesRead = inChannel.read(buf);
从Buffer中读写数据的两种方式:
**读**:使用get()方法从Buffer中读取数据。如:byte aByte = buf.get();
**写**:通Buffer的put()方法写到Buffer里。如:buf.put(127);
Channel (通道)
- 与Stream(流)的不同之处在于通道是双向的,流只能在一个方向上操作,而通道可以用于读,写或者二者同时进行,最关键的是可以和多路复用器结合起来,提供状态位,多路复用器可识别Channel所处的状态。
- 通道可以分两大类:
用于网络读写的SelectableChannel,和用于文件操作的FileChannel。具体来说:通过FileChannel可以从文件读或者向文件写入数据;通过SocketChannel,以TCP来向网络连接的两端读写数据;通过ServerSocketChanel能够监听客户端发起的TCP连接,并为每个TCP连接创建一个新的SocketChannel来进行数据读写;通过DatagramChannel,以UDP协议来向网络连接的两端读写数据。
Selector(选择器)
- Selector提供选择已经就绪的任务的能力。简单说,就是Selector会不断轮询注册在Selector上的通道(Channel),如果这个通道发生了读写操作,这个通道就会处于就绪状态,会被Selector察觉到,然后通过SelectionKey可以取出就绪的Channel集合,从而进行IO操作。
- 一个Selector可以负责成千上万的通道,没有上限。这也是JDK使用了epoll代替传统的Select实现,获得连接句柄没有限制。意味着我们只需要一个线程负责Selector的轮询,就可以接入成百上千的客户端,这是JDK NIO库的巨大进步。
- Selector类是NIO的核心类,Selector能够检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。这样一来,只是用一个单线程就可以管理多个通道,也就是管理多个连接。这样使得只有在连接真正有读写事件发生时,才会调用函数来进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程,并且避免了多线程之间的上下文切换导致的开销。
- 与Selector有关的一个关键类是SelectionKey,一个SelectionKey表示一个到达的事件,这2个类构成了服务端处理业务的关键逻辑。
标准的NIO步骤
一个简单(标准)的NIO输入输出一般包含如下步骤:
- 从数据源获取通道 ;
- 分配缓冲区 ;
- 切换缓存区为写模式;
- 从通道读取数据写入缓冲区;
- 切换缓冲区为读模式 ;
- 缓冲区数据写入通道中 ;
- 关闭资源;
本文深入探讨Java的IO和NIO系统,包括标准阻塞IO和非阻塞IO的概念,详细介绍了字节流、字符流、文件流、数组流、管道流、数据流、缓冲流、转换流、打印流和对象流。此外,还讲解了NIO中的Buffer、Channel和Selector机制,以及标准NIO的步骤。
1924

被折叠的 条评论
为什么被折叠?



