java IO 与 BIO、NIO、AIO

在Java编程中,IO(输入/输出)操作是与外部世界(如文件系统、网络、终端等)进行数据交换的关键部分。Java提供了多种IO模型,其中包括BIO(Blocking IO)、NIO(Non-blocking IO)和AIO(Asynchronous IO)。以下是对这些概念的详细解释及其之间的比较。

一、Java IO概述

Java的IO体系主要包括以下几部分:

  1. 标准IO(基于流):传统的IO操作,基于字节流和字符流,通过InputStreamOutputStreamReaderWriter等类进行数据的读写。
  2. BIO(Blocking IO):阻塞式IO,每个请求对应一个线程,适用于连接数较少的场景。
  3. NIO(Non-blocking IO):非阻塞IO,通过通道(Channel)和缓冲区(Buffer)实现,适用于高并发场景。
  4. AIO(Asynchronous IO):异步IO,通过回调机制实现,允许操作系统通知应用程序IO操作的完成。

二、BIO(Blocking IO)

1. 特点

  • 阻塞式:每个IO操作会阻塞当前线程,直到操作完成。
  • 线程模型:通常为一个连接一个线程。
  • 实现简单:编程模型直观,易于理解和实现。

2. 优缺点

优点

  • 编程模型简单,调试容易。
  • 对于连接数较少的应用,性能和资源消耗可接受。

缺点

  • 高并发时,线程数增加,导致内存消耗大、上下文切换频繁。
  • 不适用于长连接和高并发场景。

3. 使用场景

适用于连接数较少、并发要求不高的应用,如简单的文件读写、单一客户端连接的应用等。

4. 示例代码

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

import java.io.*;
import java.net.*;

public class BIOExample {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("Server started, listening on port 8080");

        while (true) {
            Socket clientSocket = serverSocket.accept(); // 阻塞等待客户端连接
            System.out.println("Client connected: " + clientSocket.getInetAddress());

            // 为每个客户端连接创建一个新线程
            new Thread(() -> handleClient(clientSocket)).start();
        }
    }

    private static void handleClient(Socket socket) {
        try (
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true)
        ) {
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                System.out.println("Received: " + inputLine);
                out.println("Echo: " + inputLine);
                if ("exit".equalsIgnoreCase(inputLine)) {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、NIO(Non-blocking IO)

1. 特点

  • 非阻塞式:IO操作不会阻塞线程,可以同时处理多个连接。
  • 基于通道和缓冲区:通过ChannelBuffer进行数据的读写。
  • 选择器(Selector)机制:通过Selector管理多个通道,监控IO事件,实现单线程处理多个连接。

2. 优缺点

优点

  • 支持高并发,资源消耗较低。
  • 可以通过单线程管理多个连接,减少线程切换开销。

缺点

  • 编程模型较复杂,理解和实现相对困难。
  • 对于简单应用,可能带来不必要的复杂性。

3. 使用场景

适用于需要处理大量并发连接的应用,如高性能的网络服务器、实时数据处理系统等。

4. 示例代码

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

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.util.Iterator;

public class NIOExample {
    public static void main(String[] args) throws IOException {
        // 创建选择器
        Selector selector = Selector.open();

        // 打开服务器通道
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress(8080));

        // 注册服务器通道到选择器,并监听连接事件
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("NIO Server started, listening on port 8080");

        while (true) {
            // 等待有事件发生
            selector.select();

            // 获取所有的选择键
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                keyIterator.remove();

                if (key.isAcceptable()) {
                    // 接受新的连接
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                    System.out.println("Client connected: " + client.getRemoteAddress());
                } else if (key.isReadable()) {
                    // 读取数据
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = client.read(buffer);

                    if (bytesRead > 0) {
                        buffer.flip();
                        byte[] data = new byte[buffer.limit()];
                        buffer.get(data);
                        String received = new String(data);
                        System.out.println("Received: " + received);

                        // 回显数据
                        buffer.rewind();
                        client.write(buffer);
                    } else if (bytesRead == -1) {
                        client.close();
                        System.out.println("Client disconnected");
                    }
                }
            }
        }
    }
}

四、AIO(Asynchronous IO)

1. 特点

  • 异步非阻塞:IO操作完全异步,通过回调机制处理完成事件。
  • 基于Future和回调:使用FutureCompletionHandler来获取IO操作结果。
  • 更高的并发性:适合需要处理大量并发连接且资源消耗需最小化的场景。

2. 优缺点

优点

  • 高并发性能更佳,资源利用率更高。
  • 编程模型更灵活,适合复杂的异步操作。

缺点

  • 编程复杂度更高,理解和实现更加困难。
  • 调试和维护相对复杂。

3. 使用场景

适用于需要极高并发处理能力的应用,如高性能网络服务器、大规模分布式系统等。

4. 示例代码

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

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.Future;

public class AIOExample {
    public static void main(String[] args) throws IOException {
        // 打开AIO服务器通道
        final AsynchronousServerSocketChannel serverChannel =
                AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));

        System.out.println("AIO Server started, listening on port 8080");

        // 接受连接请求
        serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
            @Override
            public void completed(final AsynchronousSocketChannel client, Void attachment) {
                // 继续接受下一个连接
                serverChannel.accept(null, this);

                // 处理当前连接
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                    @Override
                    public void completed(Integer bytesRead, ByteBuffer buf) {
                        if (bytesRead != -1) {
                            buf.flip();
                            byte[] data = new byte[buf.limit()];
                            buf.get(data);
                            String received = new String(data);
                            System.out.println("Received: " + received);

                            // 回显数据
                            buf.rewind();
                            client.write(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {
                                @Override
                                public void completed(Integer result, ByteBuffer attachment) {
                                    // 继续读取数据
                                    client.read(attachment, attachment, this);
                                }

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

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

            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("Failed to accept a connection.");
                exc.printStackTrace();
            }
        });

        // 防止主线程退出
        try {
            Thread.currentThread().join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

五、BIO、NIO、AIO的比较

特性BIO (Blocking IO)NIO (Non-blocking IO)AIO (Asynchronous IO)
阻塞性阻塞非阻塞异步非阻塞
线程模型一连接一线程单线程或少量线程管理多连接通过回调机制处理IO事件
适用场景低并发、简单应用高并发,中等复杂度的应用极高并发、复杂异步需求的应用
性能低到中等(受限于线程资源)高,减少了线程切换开销非常高,充分利用系统资源
编程复杂度简单中等
资源消耗高(大量线程占用内存)低(少量线程管理多连接)低(事件驱动,资源高效利用)

六、选择建议

  • 简单应用或低并发场景:使用BIO,因为其实现简单,易于维护。
  • 中高并发且需要较高性能:选择NIO,可以有效管理大量连接,提升性能。
  • 极高并发且需要高性能、复杂异步处理:选择AIO,充分利用异步特性实现高效资源管理。

七、总结

Java提供了多种IO模型,以满足不同应用场景的需求。从简单的阻塞IO(BIO)到高效的非阻塞IO(NIO)再到灵活的异步IO(AIO),开发者可以根据具体需求选择合适的IO模型,以实现最佳性能和资源利用。理解这些模型的特点、优缺点以及适用场景,对于开发高性能、高可扩展性的Java应用至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络与服务器

目录 架构体系及相关知识 三层架构&#xff1a; 四层架构&#xff1a; 常见的应用的模式&#xff1a; OSI模型 分层 数据链路层 TCP/IP模型 TCP和UDP都是传输层的协议 TCP三次握手、四次次分手 URL&HTTP协议详解 网址URL 结构化 报文行 报文头 空行 报文体…

Cursor实现go项目配置并实现仓库Gin项目运行

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a;知识备份 ✨特色专栏&#xff1a;知识分享 &#x…

141.环形链表 142.环形链表II

141.环形链表 & 142.环形链表II 141.环形链表 思路&#xff1a;快慢指针 or 哈希表 快慢指针代码&#xff1a; class Solution { public:bool hasCycle(ListNode *head) {if(headnullptr||head->nextnullptr)return false;ListNode *fasthead->next; //不能设置成…

信用租赁系统助力企业实现免押金租赁新模式

内容概要 在现代商业环境中&#xff0c;信用租赁正在迅速崛起。通过结合大数据与区块链技术&#xff0c;信用租赁系统彻底改变了传统的租赁流程。什么是信用租赁呢&#xff1f;简单说&#xff0c;就是不需要押金&#xff0c;你也能够租到你想要的物品&#xff0c;这对企业和消…

el-select下拉框在弹框里面错位

问题出现 Element Plus 是一个基于 Vue 3 的组件库&#xff0c;el-select 是其中一个用于选择器的组件。在 el-select 组件中&#xff0c;teleported 属性用于控制下拉菜单的渲染位置。 解决方法 teleported 属性「element-plus」 popper-append-to-body属性「element」 ‌…

IO进程day1

一、思维导图

力扣-21-合并两个有序链表

思路&#xff1a; 因为是升序的两个链表&#xff0c;我们可以进行数据域比大小&#xff0c;然后把p3(自己创建的)的指针域指向小的那个 注&#xff1a;一定要先判断两个指针为0的情况

人工智能的发展领域之GPU加速计算的应用概述、架构介绍与教学过程

文章目录 一、架构介绍GPU算力平台概述优势与特点 二、注册与登录账号注册流程GPU服务器类型配置选择指南内存和存储容量网络带宽CPU配置 三、创建实例实例创建步骤镜像选择与设置 四、连接实例SSH连接方法远程桌面配置 一、架构介绍 GPU算力平台概述 一个专注于GPU加速计算的…

QT实现 端口扫描暂停和继续功能 3

上篇QT给端口扫描工程增加线程2-CSDN博客 为按钮pushButton_Stop添加clicked事件&#xff0c;功能为暂停扫描&#xff0c;并在暂停后显示继续按钮&#xff0c;点击继续按钮之后继续扫描 1.更新UI 添加继续按钮 点击转到槽则会自动声明 2. 更新 MainWindow.h 需要新增的部分…

汽车微处理器安全机制以及测试介绍

本文介绍了三类汽车微处理器安全机制&#xff1a;硬件类、软件类和混合类&#xff0c;旨在提高系统的可靠性和安全性。硬件类安全机制包括逻辑内建自测试&#xff08;Logic-BIST&#xff09;、三重模块冗余&#xff08;TMR&#xff09;、内存内建自测试&#xff08;Memory-BIST…

【Azure Redis 缓存】Azure Redis 遇见的连接不上问题和数据丢失的情况解答

问题描述 PHP应用再连接Azure Redis服务时&#xff0c;出现Connection Timed out。当通过升级提高Azure Redis的性能时候&#xff0c;发现之前的数据丢失了。 image.png 问题解答 当Redis服务出现Timeout的情况时&#xff0c;可以从Redis服务的指标(Metrics)开始查看&#xff0…

python学习笔记—15—数据容器之列表

1. 数据容器 列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict) 2. 列表 (1) 定义 tmp_list ["super", "carry", "doinb"] print(f"tmp_list {tmp_list}, tmp_list type is {type(tmp_list)}") tmp_list1 ["doi…

记录一次面试中被问到的问题 (HR面)

文章目录 一、你对公司的了解多少二、为什么对这个岗位感兴趣三、不能说的离职原因四、离职原因高情商回复五、你的核心优势是什么六、你认为你比其他面试候选人的优势是什么七、不要提及情感 一、你对公司的了解多少 准备要点&#xff1a; 在面试前&#xff0c;对公司进行充分…

VLMs之Agent之CogAgent:《CogAgent: A Visual Language Model for GUI Agents》翻译与解读

VLMs之Agent之CogAgent&#xff1a;《CogAgent: A Visual Language Model for GUI Agents》翻译与解读 导读&#xff1a;这篇论文介绍了CogAgent&#xff0c;一个专注于图形用户界面 (GUI) 理解和导航的视觉语言模型 (VLM)。这篇论文提出了一种新的视觉语言模型 CogAgent&#…

linux audio(1)-pulseaudio模块数据流

本文主要讨论pulseaudio模块的数据流。这里的模块(module)主要限制在sink和source这两种类型。其他类型的数据流后续有空 再撰文讨论。 pulseaudio的模块一般会启动一路线程进行数据的搬运和处理。 下面的是module-null-source模块的数据搬运线程启动代码。 进入thread_func…

ros2-4.1 服务通信介绍

服务是ROS图中节点之间的另一种通信方法。服务分为客户端和服务端&#xff0c;客户端发送请求给服务端&#xff0c;服务端可以根据客户端的请求做一些处理&#xff0c;然后返回结果给客户端。也称为为请求-响应模型。 服务和话题的不同之处&#xff0c;话题是没有返回的&#…

微信小程序之历史上的今天

微信小程序之历史上的今天 需求描述 今天我们再来做一个小程序&#xff0c;主要是搜索历史上的今天发生了哪些大事&#xff0c;结果如下 当天的历史事件或者根据事件选择的历史事件的列表&#xff1a; 点击某个详细的历史事件以后看到详细信息&#xff1a; API申请和小程序…

数据库模型全解析:从文档存储到搜索引擎

目录 前言1. 文档存储&#xff08;Document Store&#xff09;1.1 概念与特点1.2 典型应用1.3 代表性数据库 2. 图数据库&#xff08;Graph DBMS&#xff09;2.1 概念与特点2.2 典型应用2.3 代表性数据库 3. 原生 XML 数据库&#xff08;Native XML DBMS&#xff09;3.1 概念与…

Vue3+TS+vite项目笔记1

vue2与vue3的比较 源码的升级 使用Proxy代替defineProperty实现响应式。 重写虚拟DOM的实现和Tree-Shaking。 新的特性 Composition API&#xff08;组合API&#xff09;&#xff1a; setup ref与reactive computed与watch ...... 新的内置组件&#xff1a; Fragment T…

Spring5框架之SpringMVC

目录 1.SpringMVC的入门案例 1.1 通过maven构建一个web项目 1.2 添加对应的依赖及Tomcat插件 1.3 创建SpringMVC的配置文件 1.4 在web.xml中注册DispatchServlet 1.5 创建自定义的Controller 1.6 在Springmvc配置文件中注册 原理分析&#xff1a; 2.SpringMVC基于注解的…