12 BIO,NIO,AIO的区别
vvEcho
2024-01-24 10:33:23
Categories:
02 java基础
Tags:
面试
BIO、NIO、AIO 是Java中处理I/O操作的不同方式,它们的区别如下:
- BIO(Blocking I/O):阻塞式I/O,即在执行I/O操作时,当前线程会被阻塞,直到I/O操作完成。这种方式适用于简单的I/O操作,但当有大量的并发请求时,性能较差。
核心机制:
每个连接对应一个独立线程,线程在I/O操作期间被完全阻塞,直到数据就绪或操作完成 1 3。
典型实现如ServerSocket和Socket,通过accept()和read()方法阻塞等待客户端请求
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import java.io.*;
public class BioExample { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("input.txt"); int data = fis.read(); while (data != -1) { System.out.print((char) data); data = fis.read(); } fis.close(); } }
|
在这个例子中,我们使用FileInputStream进行文件读取,由于使用了阻塞式I/O,所以在读取文件时,当前线程会被阻塞,直到文件读取完成。
- NIO(Non-blocking I/O):非阻塞式I/O,即在执行I/O操作时,不会阻塞当前线程,而是通过回调函数或轮询的方式检查I/O操作是否完成。这种方式适用于高并发的场景,性能较好。
核心机制:
基于多路复用器(Selector),单个线程可监听多个通道(Channel)的就绪事件(如读/写),通过轮询实现非阻塞 2 4。
使用Buffer和Channel替代传统流式I/O,支持零拷贝技术提升性能
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.nio.*; import java.nio.channels.*;
public class NioExample { public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if (key.isAcceptable()) { } else if (key.isReadable()) { } iterator.remove(); } } } }
|
在这个例子中,我们使用Selector和ServerSocketChannel进行非阻塞式文件读取,通过轮询的方式检查文件读取是否完成。
- AIO(Asynchronous I/O):异步I/O,由操作系统内核来完成I/O操作,减少线程切换开销,提高性能;线程完全非阻塞,线程资源利用率极高,适合海量并发。
核心机制:
基于异步回调或事件驱动,由操作系统内核完成I/O操作后通知应用程序,无需线程主动等待
如AsynchronousSocketChannel和CompletionHandler,操作发起后立即返回,内核完成读写后通过回调通知结果
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.nio.*; import java.nio.channels.*; import java.util.concurrent.*;
public class AioExample { public static void main(String[] args) throws IOException, InterruptedException { AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("input.txt"), StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; long count = fileChannel.size();
Future<Integer> operation = fileChannel.read(buffer, position); while (!operation.isDone()) { }
int bytesRead = operation.get(); buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } fileChannel.close(); } }
|
在这个例子中,我们使用AsynchronousFileChannel进行异步文件读取,通过回调函数通知文件读取完成。
总结:BIO-阻塞式io,通俗理解去银行取钱,银行只开了一个窗口得一个一个来取【线程阻塞,资源消耗大】
NIO-非阻塞式io,通俗理解去银行取钱,取完号后可以自由活动,但是得定期看看电子大屏看是否轮到自己,当窗口准备好时,用户需自行前往办理(数据拷贝仍需阻塞等待)【多路复用,主动轮询就绪事件】
AIO-异步非阻塞io,通俗理解你要取钱,但是你没有时间自己去取,你向银行提交申请后,银行派人把钱给你送来【内核完成所有操作并主动回调,用户全程无感】