首页常见问题正文

BIO、NIO、AIO 有什么区别?

更新时间:2023-03-22 来源:黑马程序员 浏览量:

IT培训班

  BIO、NIO、AIO 都是 Java 中用于实现网络编程的三种不同的方式,它们有以下区别:

  1.BIO (Blocking I/O):传统的阻塞式 I/O,每个连接都需要一个线程来处理,当连接数较多时,会导致系统资源消耗严重,性能较差。

  2.NIO (Non-blocking I/O):非阻塞式 I/O,通过使用单线程轮询多个连接的方式来实现高效的处理方式,可以支持较大数量的并发连接,但编程模型较为复杂。

  3.AIO (Asynchronous I/O):异步 I/O,通过回调方式实现高效的 I/O 操作,可以大大降低系统资源的消耗,适用于高并发、高吞吐量的场景,但在实际使用中可能会受到操作系统和硬件的限制。

  下面是 Java 中分别使用 BIO、NIO、AIO 实现简单的网络通信的示例代码:

  BIO 示例代码:

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

public class BioServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(() -> {
                try {
                    InputStream inputStream = socket.getInputStream();
                    OutputStream outputStream = socket.getOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, len);
                    }
                    outputStream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

  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 {
 
    private Selector selector;
 
    public static void main(String[] args) throws IOException {
        new NioServer().startServer();
    }
 
    public void startServer() throws IOException {
        selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 8000));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("Server started on port 8000...");
 
        while (true) {
            selector.select();
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    acceptConnection(key);
                } else if (key.isReadable()) {
                    readFromClient(key);
                }
                keyIterator.remove();
            }
        }
    }
 
    private void acceptConnection(SelectionKey key) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel socketChannel = serverChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        System.out.println("Connection accepted from client: " + socketChannel.getRemoteAddress());
    }
 
    private void readFromClient(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = socketChannel.read(buffer);
        if (bytesRead == -1) {
            socketChannel.close();
            System.out.println("Connection closed by client: " + socketChannel.getRemoteAddress());
        } else {
            byte[] data = new byte[bytesRead];
            buffer.flip();
            buffer.get(data, 0, bytesRead);
            System.out.println("Received message from client: " + new String(data));
            socketChannel.write(ByteBuffer.wrap("Hello from server".getBytes()));
        }
    }
}

  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) throws IOException {
        AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8080));
        serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
            @Override
            public void completed(AsynchronousSocketChannel result, Object attachment) {
                serverSocketChannel.accept(null, this);
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                    @Override
                    public void completed(Integer result, ByteBuffer buffer) {
                        if (result > 0) {
                            buffer.flip();
                            byte[] bytes = new byte[buffer.limit()];
                            buffer.get(bytes);
                            System.out.println(new String(bytes));
                            buffer.clear();
                            result.write(ByteBuffer.wrap("Hello, client!".getBytes()));
                        } else if (result == -1) {
                            try {
                                result.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    @Override
                    public void failed(Throwable exc, ByteBuffer attachment) {
                        try {
                            result.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }

            @Override
            public void failed(Throwable exc, Object attachment) {
                exc.printStackTrace();
            }
        });
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  这些代码仅作为简单的演示,实际应用中需要考虑更多的细节和异常处理。

分享到:
在线咨询 我要报名
和我们在线交谈!