首頁常見問題正文

BIO、NIO、AIO 有什么區(qū)別?

更新時間:2023-03-22 來源:黑馬程序員 瀏覽量:

IT培訓班

  BIO、NIO、AIO 都是 Java 中用于實現(xiàn)網(wǎng)絡編程的三種不同的方式,它們有以下區(qū)別:

  1.BIO (Blocking I/O):傳統(tǒng)的阻塞式 I/O,每個連接都需要一個線程來處理,當連接數(shù)較多時,會導致系統(tǒng)資源消耗嚴重,性能較差。

  2.NIO (Non-blocking I/O):非阻塞式 I/O,通過使用單線程輪詢多個連接的方式來實現(xiàn)高效的處理方式,可以支持較大數(shù)量的并發(fā)連接,但編程模型較為復雜。

  3.AIO (Asynchronous I/O):異步 I/O,通過回調方式實現(xiàn)高效的 I/O 操作,可以大大降低系統(tǒng)資源的消耗,適用于高并發(fā)、高吞吐量的場景,但在實際使用中可能會受到操作系統(tǒng)和硬件的限制。

  下面是 Java 中分別使用 BIO、NIO、AIO 實現(xiàn)簡單的網(wǎng)絡通信的示例代碼:

  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();
            }
        }
    }
}

  這些代碼僅作為簡單的演示,實際應用中需要考慮更多的細節(jié)和異常處理。

分享到:
在線咨詢 我要報名
和我們在線交談!