当前位置: 首页 > news >正文

【java】BIO,NIO,多路IO复用,AIO

在Java中,处理I/O操作的模型主要有四种:阻塞I/O (BIO), 非阻塞I/O (NIO), 异步I/O (AIO), 以及IO多路复用。下面详细介绍这四种I/O模型的工作原理和应用场景。

1. 阻塞I/O (BIO)

工作原理

阻塞I/O是最传统的I/O模型。在这种模型中,当一个线程发起一个I/O请求(如读写操作)时,该线程会被阻塞,直到I/O操作完成。这意味着线程必须等待I/O操作完成才能继续执行。

代码示例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;public class BioServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8080);System.out.println("Server started on port 8080");while (true) {Socket clientSocket = serverSocket.accept(); // 阻塞等待客户端连接new Thread(() -> {try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {String line;while ((line = reader.readLine()) != null) {System.out.println("Received: " + line);}} catch (IOException e) {e.printStackTrace();}}).start();}}
}
优点
  • 实现简单。
缺点
  • 每个连接都需要一个线程来处理,当并发连接数增加时,线程的数量也会增加,可能导致系统资源耗尽。

2. 非阻塞I/O (NIO)

工作原理

非阻塞I/O模型允许线程在发起I/O请求时不会被阻塞,如果数据不可用或设备忙,则立即返回一个错误或特殊值。线程可以选择立即再次尝试I/O操作或去做其他事情,从而提高了CPU的利用率。

代码示例
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;
import java.util.Set;public class NioServer {public static void main(String[] args) throws IOException {Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(8080));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int readBytes = sc.read(buffer);if (readBytes > 0) {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("Received: " + new String(data));}}keyIterator.remove();}}}
}
优点
  • 提高了单个线程处理多个连接的能力,降低了系统资源消耗。
  • 可以处理大量并发连接。
缺点
  • 实现相对复杂。
  • 需要手动管理缓冲区、选择器等。

3. IO多路复用

工作原理

IO多路复用允许一个进程同时监听多个文件描述符(例如socket),并只在某个描述符准备好进行读写操作时才进行处理。常用的多路复用机制有selectpollepoll。这种模型非常适合处理大量并发连接的场景。

代码示例
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;public class SelectServer {public static void main(String[] args) throws IOException {Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(8080));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();for (SelectionKey key : selector.selectedKeys()) {if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();// 读取数据...}}selector.selectedKeys().clear();}}
}
优点
  • 可以同时监听多个文件描述符,提高处理大量并发连接的能力。
  • 提高了资源利用率。
缺点
  • 在Java中,selectpoll的性能不如epoll,后者仅在Linux系统中可用。

4. 异步I/O (AIO)

工作原理

异步I/O是真正的异步操作模型,进程发起I/O请求后可以立即返回并继续执行其他任务,而无需等待I/O操作完成。当I/O操作完成后,操作系统会通知进程结果。

代码示例
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;public class AioServer {private static final CountDownLatch latch = new CountDownLatch(1);public static void main(String[] args) throws IOException, InterruptedException {AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new java.net.InetSocketAddress(8080));server.accept(null, new AcceptHandler(server));latch.await();}static class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {private AsynchronousServerSocketChannel server;public AcceptHandler(AsynchronousServerSocketChannel server) {this.server = server;}@Overridepublic void completed(AsynchronousSocketChannel result, Object attachment) {result.read(ByteBuffer.allocate(1024), null, new ReadHandler(result));server.accept(null, this);}@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();latch.countDown();}}static class ReadHandler implements CompletionHandler<Integer, Object> {private AsynchronousSocketChannel channel;public ReadHandler(AsynchronousSocketChannel channel) {this.channel = channel;}@Overridepublic void completed(Integer result, Object attachment) {ByteBuffer buffer = (ByteBuffer) attachment;buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("Received: " + new String(data));channel.close();}@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();try {((AsynchronousSocketChannel) attachment).close();} catch (IOException e) {e.printStackTrace();}}}
}
优点
  • 真正的异步操作,提高了系统的并发能力和响应速度。
  • 适用于高并发场景。
缺点
  • 实现较为复杂。
  • Java中AIO的支持相对较少,不如NIO成熟。

总结

  • BIO:适合连接数较少的场景。
  • NIO:适用于中等并发的场景,提高了资源利用率。
  • IO多路复用:适合大量并发连接的场景,特别是在服务器端。
  • AIO:适用于高并发场景,真正实现了异步操作。

选择哪种模型取决于具体的应用场景和需求。例如,对于需要处理大量并发连接的服务器,IO多路复用和异步I/O可能是更佳的选择。而对于简单的、单线程的应用,阻塞I/O可能就已经足够。

相关文章:

【java】BIO,NIO,多路IO复用,AIO

在Java中&#xff0c;处理I/O操作的模型主要有四种&#xff1a;阻塞I/O (BIO), 非阻塞I/O (NIO), 异步I/O (AIO), 以及IO多路复用。下面详细介绍这四种I/O模型的工作原理和应用场景。 1. 阻塞I/O (BIO) 工作原理 阻塞I/O是最传统的I/O模型。在这种模型中&#xff0c;当一个线…...

服务器怎样减少带宽消耗的问题?

择业在使用服务器的过程中会消耗大量的带宽资源&#xff0c;而减少服务器的带宽消耗则可以帮助企业降低经济成本&#xff0c;同时还能够提高用户的访问速度&#xff0c;那么服务器怎样能减少带宽的消耗呢&#xff1f;本文就来带领大家一起来探讨一下吧&#xff01; 企业可以选择…...

linux 报错:bash: /etc/profile: 行 32: 语法错误:未预期的文件结束符

目录 注意错误不一定错在最后一行 i进入编辑 esc退出编辑 &#xff1a;wq 保存编辑退出 &#xff1a;q&#xff01;不保存退出 if [ $# -eq 3 ] then if [ ! -e "$1" ]; then miss1 $1 elif [ ! -e "$2" -a ! -e "$3" ]; then miss2and3…...

MySQL练习(5)

作业要求&#xff1a; 实现过程&#xff1a; 一、触发器 &#xff08;1&#xff09;建立两个表&#xff1a;goods&#xff08;商品表&#xff09;、orders&#xff08;订单表&#xff09; &#xff08;2&#xff09;在商品表中导入商品记录 &#xff08;3&#xff09;建立触发…...

泛型新理解

1.创建三个类&#xff0c;并写好对应关系 package com.jmj.gulimall.study;public class People { }package com.jmj.gulimall.study;public class Student extends People{ }package com.jmj.gulimall.study;public class Teacher extends People{ }2.解释一下这三个方法 pub…...

JavaSE--基础语法--继承和多态(第三期)

一.继承 1.1我们为什么需要继承? 首先&#xff0c;Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程…...

高级java每日一道面试题-2024年7月23日-什么时候用包装类, 什么时候用原始类

面试官: 你在什么时候用包装类, 什么时候用原始类? 我回答: 在Java开发中&#xff0c;理解何时使用包装类&#xff08;Wrapper Classes&#xff09;和何时使用原始类&#xff08;Primitive Types&#xff09;是非常重要的。这主要取决于你的具体需求以及Java语言本身的一些限…...

LINUX之MMC子系统分析

目录 1. 概念1.1 MMC卡1.2 SD卡1.3 SDIO 2. 总线协议2.1 协议2.2 一般协议2.3 写数据2.4 读数据2.5 卡模式2.5.1 SD卡模式2.5.2 eMMC模式 2.6 命令2.6.1 命令类2.6.2 详细命令 2.7 应答2.8 寄存器2.8.1 OCR2.8.2 CID2.8.3 CSD2.8.4 RCA2.8.5 扩展CSD 3. 关键结构3.1 struct sdh…...

VulnHub:cengbox1

靶机下载地址&#xff0c;下载完成后&#xff0c;用VirtualBox打开靶机并修改网络为桥接即可搭建成功。 信息收集 主机发现和端口扫描 扫描攻击机&#xff08;192.168.31.218&#xff09;同网段存活主机确认目标机ip&#xff0c;并对目标机进行全面扫描。 nmap 192.168.31.…...

MySQL第一阶段:多表查询、事务

继续我的MySQL之旅&#xff0c;继续上篇的DDL、DML、DQL、以及一些约束&#xff0c;该到了多表查询和事务的学习总结&#xff0c;以及相关的案例实现&#xff0c;为未来的复习以及深入的理解做好知识储备。 目录 多表查询 连接查询 内连接 外连接 子查询 事务 事务简介…...

Java的序列化和反序列化

序列化&#xff1a; 将数据结构或对象转换成二进制串的过程 反序列化&#xff1a;将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程 至于为什么要序列化和反序列化呢&#xff1f; 因为互联网的产生带来了机器间通讯的需求&#xff0c;而互联通讯的双方需要采用约…...

本地连接远程阿里云K8S

1.首先安装kubectl 1.1验证自己系统 uname -m 1.2 按照步骤安装 在 Linux 系统中安装并设置 kubectl | Kubernetes 1.3 阿里云配置 通过kubectl连接Kubernetes集群_容器服务 Kubernetes 版 ACK(ACK)-阿里云帮助中心 2.验证 阿里云config直接导出&#xff0c;直接扔到.…...

CasaOS设备使用Docker安装SyncThing文件同步神器并实现远程管理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

k210 图像操作详解(一)(直线检测、边缘检测、色块追踪)

1、直线检测 ##################################################################################################### # file main.py # author 正点原子团队(ALIENTEK) # version V1.0 # date 2024-01-17 # brief image图像特征检测实…...

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…...

DevExpress WinForms自动表单布局,创建高度可定制用户体验(二)

使用DevExpress WinForms的表单布局组件可以创建高度可定制的应用程序用户体验&#xff0c;从自动安排UI控件到按比例调整大小&#xff0c;DevExpress布局和数据布局控件都可以让您消除与基于像素表单设计相关的麻烦。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&a…...

vue中v-if和v-for

vue中v-if和v-for Vue 官方建议不要在同一个元素上同时使用 v-if 和 v-for 指令&#xff0c;主要有以下几个原因&#xff1a; 性能问题&#xff1a; 当 v-if 和 v-for 一起使用时&#xff0c;Vue 在每次渲染时都需要先执行循环&#xff0c;然后再对每个元素进行条件判断。这可能…...

【MySQL】根据binlog日志获取回滚sql的一个开发思路

根据binlog日志获取回滚sql的一个开发思路 需要获取的信息 thread_id 打开 mysql 客户端 开始时间 关闭 mysql 客户端 结束时间 binlog 匹配流程 指定 mysql 客户端 开始时间和结束时间 先匹配 thread_id 相同的 然后匹配 ^BEGIN$行和 ^COMMIT/*!*/;$行之间的数据 当匹…...

Kafka快速入门+SpringBoot简单的秒杀案例

1. 主题相关 1.1 创建主题 kafka-topics.sh --create --bootstrap-server [服务器地址] --replication-factor [副本数] --partitions [分区数] --topic [主题名]liberliber-VMware-Virtual-Platform:/home/zookeeper$ docker-compose exec kafka /bin/bash #进入kafka容器 b…...

Redis哨兵机制

哨兵机制&#xff1a; &#xff08;1&#xff09;监控&#xff1a;有一个哨兵集群&#xff0c;这个哨兵集群检测redis的主从集群。它是每隔1秒钟就向主从集群中的节点发送心跳&#xff0c;如果节点没有回复&#xff0c;则这个哨兵就主观的认为这个节点发生故障&#xff0c;这时…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...