Java BIO、NIO、AIO 有什么区别?

发布时间:2024年01月05日

Java BIO、NIO、AIO 有什么区别?

Java中的BIO、NIO和AIO分别代表着阻塞式I/O、非阻塞式I/O和异步I/O。它们之间的主要区别在于处理I/O操作的方式。

1. 阻塞式I/O(BIO)

BIO采用阻塞式的方式,即当一个线程执行一个I/O操作时,该线程会被阻塞,直到I/O操作完成。这意味着在进行网络通信时,每个连接都需要一个独立的线程,会导致资源消耗较大。

以下是一个简单的BIO服务器的示例:

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

public class BioServer {

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            while (true) {
                // 阻塞等待客户端连接
                Socket socket = serverSocket.accept();

                // 每个连接创建一个线程处理
                new Thread(() -> {
                    try (InputStream inputStream = socket.getInputStream()) {
                        byte[] buffer = new byte[1024];
                        int length;
                        // 阻塞读取数据
                        while ((length = inputStream.read(buffer)) != -1) {
                            System.out.println(new String(buffer, 0, length));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 非阻塞式I/O(NIO)

NIO使用了非阻塞式的方式,通过Selector选择器实现。一个线程可以处理多个连接,当一个连接的I/O操作不可用时,线程可以切换到处理其他连接。

以下是一个简单的NIO服务器的示例:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class NioServer {

    public static void main(String[] args) {
        try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
             Selector selector = Selector.open()) {

            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            while (true) {
                selector.select();
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();

                    if (key.isAcceptable()) {
                        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                        SocketChannel socketChannel = serverChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int bytesRead = socketChannel.read(buffer);
                        if (bytesRead > 0) {
                            buffer.flip();
                            System.out.println(new String(buffer.array(), 0, bytesRead));
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 异步I/O(AIO)

AIO使用异步方式处理I/O操作,通过回调函数通知应用程序。AIO对于处理大量连接时表现更好,因为不需要为每个连接分配一个线程。

以下是一个简单的AIO服务器的示例:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class AioServer {

    public static void main(String[] args) {
        try (AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open()) {
            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
                @Override
                public void completed(AsynchronousSocketChannel socketChannel, Void attachment) {
                    serverSocketChannel.accept(null, this);

                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    socketChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                        @Override
                        public void completed(Integer bytesRead, ByteBuffer buffer) {
                            buffer.flip();
                            System.out.println(new String(buffer.array(), 0, bytesRead));
                        }

                        @Override
                        public void failed(Throwable exc, ByteBuffer buffer) {
                            exc.printStackTrace();
                        }
                    });
                }

                @Override
                public void failed(Throwable exc, Void attachment) {
                    exc.printStackTrace();
                }
            });

            // 阻塞主线程,保

持服务端运行
            Thread.sleep(Long.MAX_VALUE);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这个示例中,当有连接建立时,通过CompletionHandler处理读取数据的异步操作。

文章来源:https://blog.csdn.net/sanmansan/article/details/135347296
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。