Java中网络IO的实现方式(BIO、NIO、AIO)介绍

Java中网络IO的实现方式主要有BIO、NIO、AIO三种。下面分别进行介绍。

BIO

BIO即Blocking IO,阻塞式IO,是一种传输方式。BIO的特点是同步阻塞,也就是说,客户端请求到来后,服务器必须处理完该请求才能执行下一步操作,高并发下无法满足需求。使用BIO方式,可以使用SocketServerSocket类进行通信。

下面是一个BIO的示例,该示例利用BIO模拟了一个简单的服务器。

public class SocketHandler extends Thread {
    private InputStream inputStream;
    private OutputStream outputStream;

    public SocketHandler(Socket socket) throws IOException {
        inputStream = socket.getInputStream();
        outputStream = socket.getOutputStream();
    }

    @Override
    public void run() {
        try {
            byte[] buffer = new byte[1024];
            int len = 0;
            if ((len = inputStream.read(buffer)) != -1) {
                String request = new String(buffer, 0, len);
                String response = "response to " + request;
                outputStream.write(response.getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Server {
    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8899);
        while (true) {
            Socket socket = serverSocket.accept();
            SocketHandler socketHandler = new SocketHandler(socket);
            socketHandler.start();
        }
    }

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.start();
    }
}

NIO

NIO即New IO,新IO,是JDK的1.4版本中引入的新特性。相对于BIO的同步阻塞,NIO采用事件驱动机制,利用轮询的方式进行事件的处理,因此可以更好地支持高并发。使用NIO方式,可以使用ChannelSelector类进行通信。

下面是一个NIO的示例,该示例利用NIO模拟了一个简单的服务器。

public class SocketHandler implements Runnable {
    private SocketChannel socketChannel;
    private Selector selector;
    private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

    public SocketHandler(SocketChannel socketChannel, Selector selector) throws IOException {
        this.socketChannel = socketChannel;
        this.selector = selector;
    }

    @Override
    public void run() {
        try {
            while (true) {
                int readyChannels = selector.select();
                if (readyChannels == 0) continue;
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    if (selectionKey.isReadable()) {
                        byteBuffer.clear();
                        socketChannel.read(byteBuffer);
                        byteBuffer.flip();
                        String request = new String(byteBuffer.array(), 0, byteBuffer.limit());
                        String response = "response to " + request;
                        socketChannel.write(ByteBuffer.wrap(response.getBytes()));
                    }
                    iterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socketChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Server {
    public void start() throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(8899));
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) continue;
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    new Thread(new SocketHandler(socketChannel, selector)).start();
                }
                iterator.remove();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.start();
    }
}

AIO

AIO即Asynchronous IO,异步IO,在JDK的1.7版本中引入。相对于NIO的轮询方式,AIO采用异步回调的方式进行事件的处理,更加符合面向对象的思想。使用AIO方式,可以使用AsynchronousServerSocketChannelCompletionHandler类进行通信。

下面是一个AIO的示例,该示例利用AIO模拟了一个简单的服务器。

public class SocketHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {
    private AsynchronousServerSocketChannel serverSocketChannel;

    public SocketHandler(AsynchronousServerSocketChannel serverSocketChannel) {
        this.serverSocketChannel = serverSocketChannel;
    }

    @Override
    public void completed(AsynchronousSocketChannel socketChannel, Object attachment) {
        try {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            socketChannel.read(buffer, attachment, new CompletionHandler<Integer, Object>() {
                @Override
                public void completed(Integer result, Object attachment) {
                    try {
                        buffer.flip();
                        String request = new String(buffer.array(), 0, buffer.limit());
                        String response = "response to " + request;
                        socketChannel.write(ByteBuffer.wrap(response.getBytes()));
                        buffer.clear();
                        socketChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                    exc.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serverSocketChannel.accept(attachment, this);
        }
    }

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

public class Server {
    public void start() throws Exception {
        AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8899));
        serverSocketChannel.accept(null, new SocketHandler(serverSocketChannel));
        System.in.read();
    }

    public static void main(String[] args) throws Exception {
        Server server = new Server();
        server.start();
    }
}

以上就是Java中网络IO的实现方式,包括BIO、NIO、AIO三种,分别适用于不同的场景。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中网络IO的实现方式(BIO、NIO、AIO)介绍 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 如何配置Eclipse实现定制登录界面

    如何配置Eclipse实现定制登录界面 介绍 Eclipse是一种常见的集成开发环境(IDE),可以用于许多不同的编程语言。为了简化开发者经常使用的Eclipse的登录窗口实现安装一个第三方插件。这个插件可以实现自定义的登录界面,使其符合你所需的需求。在本文中,我们将讨论如何配置Eclipse实现定制化登录界面并提供两个示例。 步骤 步骤1: 安装插件 我们…

    Java 2023年5月20日
    00
  • 详解Spring Boot Security工作流程

    下面我将详细讲解 Spring Boot Security 工作流程的完整攻略。 一、什么是 Spring Boot Security Spring Boot Security 基于 Spring Security,是一款用于 Spring Boot 应用程序的 Spring Security 扩展。它提供了一些便捷的方式来配置和使用 Spring Secu…

    Java 2023年5月19日
    00
  • SpringBoot配置文件properties和yml的实现

    下面是关于SpringBoot配置文件(properties和yml)的实现攻略。 在SpringBoot应用中,配置文件(properties或yml)主要用于配置应用程序的参数。SpringBoot的默认配置文件位置是 “/src/main/resources/application.properties” 或“/src/main/resources/a…

    Java 2023年5月26日
    00
  • GC 日志的作用是什么?

    以下是关于 GC 日志的作用的完整使用攻略: GC 日志的作用是什么? GC 日志是 Java 虚拟机在进行垃圾回收时所产生的日志信息,它记录了垃圾回收的详细过程,包括垃圾回收的类型、回收的时间、回收的对象数量、回收所占用的时间等。GC 日志可以帮助开发人员了解垃圾回收的情况,优化程序的性能和效率。 GC 日志的作用 GC 日志的作用主要有以下几点: 监控垃…

    Java 2023年5月12日
    00
  • Zend Studio (eclipse)使用速度优化方法

    Zend Studio (Eclipse)使用速度优化方法 Zend Studio是一个在Eclipse基础上扩展的PHP IDE,提供了众多的功能,但是在使用中可能会出现卡顿、启动慢等问题。本文将给出一些常见的优化方法,以提高Zend Studio的使用效率。 1. 调整启动参数 默认情况下,Zend Studio会使用JVM的默认设置进行启动,这可能会导…

    Java 2023年6月15日
    00
  • Java经典面试题最全汇总208道(三)

    针对“Java经典面试题最全汇总208道(三)”的攻略,我将会进行详细的讲解,包括其中每个问题的答案和解释。 标题 Java经典面试题最全汇总208道(三) 代码块 下面是一道比较常见的Java面试题: public class Test{ public static void main(String[] args) { String str1 = new …

    Java 2023年5月23日
    00
  • php 目录与文件处理-郑阿奇(续)

    针对 “php 目录与文件处理-郑阿奇(续)” 这一主题,以下是一份完整的攻略: 一、概述 该篇文章主要讲解了PHP中如何进行目录及文件处理,包括如何创建、重命名、删除文件和目录,同时也介绍了如何读取目录中的文件等基本操作。 二、PHP中的文件处理 2.1 创建文件 使用 PHP 提供的 file_put_contents 函数可以快速的创建文件,示例如下:…

    Java 2023年6月15日
    00
  • 基于Java中字符串indexof() 的使用方法

    基于Java中字符串indexof() 的使用方法攻略 简介 在Java编程中,字符串是一种非常重要的数据类型,字符串操作是开发中常见的任务。字符串中indexof()方法就是字符串操作中的一个重要方法,它用于查找一个字符串中是否包含指定的字符或子字符串。 使用步骤 使用字符串中的indexof()方法需要遵循以下步骤: 创建一个字符串 java Strin…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部