分布式理论、架构设计学习:BIO、NIO、AIO

Java IO/NIO/AIO详解:从同步异步到阻塞非阻塞
本文详细介绍了Java中的BIO、NIO和AIO的区别与应用场景。从同步异步、阻塞非阻塞的概念出发,通过实例解释了三种IO模型的工作原理。BIO是传统的同步阻塞IO,每个连接需要一个独立的线程处理。NIO引入了通道和选择器,实现了非阻塞IO,通过单一线程轮询多个连接的IO事件。AIO(异步IO)则在数据准备完成时才通知应用程序,实现真正的异步操作。

1. 同步和异步

同步(synchronize)、异步(asychronize)是指应用程序和内核的交互而言的

  • 同步
    指用户进程触发IO操作等待或者轮训的方式查看IO操作是否就绪。

同步举例:银行取钱,我自己去取钱,取钱的过程中等待

  • 异步
    当一个异步进程调用发出之后,调用者不会立刻得到结果。而是在调用发出之后,被调用者通过状态、通知来通知调用者,或者通过回调函数来处理这个调用。

说明: 使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,OS需要支持异步IO操作

异步举例:我请朋友帮我取钱,他取到钱后返回给我(委托给操作系统OS,OS需要支持IO异步API)

2. 阻塞和非阻塞

阻塞和非阻塞是针对于进程访问数据的时候,根据IO操作的就绪状态来采取不同的方式

简单点说就是一种读写操作方法的实现方式。 阻塞方式下读取和写入将一直等待, 而非阻塞方式下,读取和写入方法会理解返回一个状态值

  • 阻塞
    ATM机排队取款,你只能等待排队取款(使用阻塞IO的时候,Java调用会一直阻塞到读写完成才返回。)

  • 非阻塞
    柜台取款,取个号,然后坐在椅子上做其他事,等广播通知,没到你的号你就不能去,但你可以不断的问大堂经理排到了没有。(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)

老张煮开水。 老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。

  1. 老张把水壶放到火上,站立着等水开。(同步阻塞)
  2. 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
  3. 老张把响水壶放到火上,立等水开。(异步阻塞)
  4. 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)

3. BIO

同步阻塞IO。B代表blocking
服务器实现模式为一个连接一个线程,即客户端有连接请求时,服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

适用场景:Java1.4之前唯一的选择,简单易用但资源开销太高
在这里插入图片描述

  • 服务端代码
package com.study;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class IOServer {
   
   
    public static void main(String[] args) throws IOException {
   
   
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress("127.0.0.1",9999));
        while (true){
   
   
            final Socket socket = serverSocket.accept(); // 同步阻塞
            new Thread(() -> {
   
   
                byte[] bytes = new byte[1024];
                try {
   
   
                    int len = socket.getInputStream().read(bytes); // 同步阻塞
                    System.out.println(new String(bytes,0,len));
                    socket.getOutputStream().write(bytes,0,len);
                    socket.getOutputStream().flush();
                } catch (IOException e) {
   
   
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
  • 客户端代码
package com.study;

import java.io.IOException;
import java.net.Socket;

public class IOClient {
   
   

    public static void main(String[] args) throws IOException {
   
   
        Socket socket = new Socket("127.0.0.1",9999);
        socket.getOutputStream().write("hello".getBytes());
        socket.getOutputStream().flush();
        System.out.println("server send back data =====");
        byte[] bytes 
### BIONIOAIO 的定义及区别 在计算机网络通信中,BIO(Blocking IO)、NIO(Non-blocking IO)和 AIO(Asynchronous IO)是常见的三种 IO 模型。以下是它们的定义及主要区别: #### 1. 阻塞式 IO(BIO) 阻塞式 IO 是最传统的 IO 模型,每个连接都需要一个独立的线程来处理请求和响应。当线程执行读写操作时,它会一直等待数据传输完成或超时,期间无法处理其他任务[^1]。因此,BIO 在高并发场景下性能较差,因为需要为每个连接分配单独的线程资源。 ```java ServerSocket serverSocket = new ServerSocket(8080); while (true) { Socket socket = serverSocket.accept(); // 阻塞在这里等待客户端连接 new Thread(() -> handleRequest(socket)).start(); } ``` #### 2. 非阻塞式 IO(NIO) 非阻塞式 IO 允许线程在执行读写操作时不被阻塞,而是立即返回结果。如果当前没有数据可读或写入未完成,线程不会等待,而是继续执行其他任务[^2]。通过使用选择器(Selector),NIO 可以在一个线程中同时管理多个连接,从而提高并发性能。 ```java 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(); } } ``` #### 3. 异步 IO(AIO) 异步 IO 是一种更高级的 IO 模型,操作系统会在数据准备就绪后主动通知应用程序进行处理。在这种模式下,线程既不需要阻塞等待数据,也不需要轮询检查状态,而是由系统负责完成整个 IO 操作并回调通知结果[^3]。AIO 提供了更高的并发性能,但其实现机制较为复杂,且在某些平台上支持程度有限。 ```java AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(8080)); serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void completed(AsynchronousSocketChannel result, Void attachment) { // 处理新连接 } @Override public void failed(Throwable exc, Void attachment) { // 处理错误 } }); ``` ### 区别与应用场景 | 特性/模型 | BIO | NIO | AIO | |-----------|-----|-----|-----| | 线程模型 | 每个连接一个线程 | 单线程管理多个连接 | 单线程管理多个连接 | | 并发性能 | 较低 | 中等 | 较高 | | 实现复杂度 | 简单 | 中等 | 高 | | 适用场景 | 小规模并发 | 中等规模并发 | 大规模并发 | - **BIO**:适用于低并发场景,如简单的 Web 应用或内部服务接口[^4]。 - **NIO**:适用于中等规模并发场景,尤其是需要高效利用线程资源的情况[^5]。 - **AIO**:适用于高并发场景,例如大规模分布式系统中的消息队列或实时通信服务[^6]。 ### 注意事项 尽管 AIO 提供了最高的并发性能,但由于其复杂的实现和对底层操作系统的依赖,在实际应用中可能并不总是最佳选择。开发者应根据具体需求权衡不同 IO 模型的优缺点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值