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

Java IO流(二)IO模型(BIO|NIO|AIO)

概述

Java IO模型同步阻塞IO(BIO)、同步非阻塞IO(NIO)、异步非阻塞IO(AIO/NIO2),Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装

IO模型

BIO(Blocking I/O)

概述

BIO是一种同步并阻塞模式,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善,但是本质上的缺点并没有得到改进(Java IO流(一)IO基础实践代码均为基于BIO)

适用场景

适用于连接数目比较少(小于单机1000)且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解

NIO(New I/O)

概述

NIO是一种同步非阻塞模式,是从JDK1.4引入的新的IO API,可以替代标准的BIO,NIO支持面向缓冲区的、基于Channel的IO操作(Channel负责传输,Buffer负责存储),以更加高效的方式进行文件的读写操作

执行流程

# selector+selectionKey(SocketChannel+selector)可监听连接、读、写
1.服务端:启动,新建ServerSocketChannel,注册到selector,生成selectionKey(ServerSocketChannel+selector),负责监听连接事件。
2.客户端:启动,新建SocketChannel和selector,然后与服务端端口建立连接。
3.服务端:selector监听到连接,取出第1步的selectionKey,取到ServerSocketChannel,用ServerSocketChannel新建一个SocketChannel,注册到selector负责监听读操作。
4.客户端:建立连接成功后,把SocketChannel注册到客户端的selector,生成selectionKey,负责监听连接事件。
5.客户端:监听到第4步连接成功。取出第4步新建的selectionKey,取出SocketChannel,向该Channel写入"HelloServer",并把该Channel注册到selector,负责监听读事件。
6.服务端:第3步中监听读事件的selector,监听到第5步客户端的事件。从selector中取出channel(第3步中的那个channel),从通道中读取到数据"HelloServer"。然后向通道写数据"HelloClient"。
7.客户端:第5步中最后负责监听的selector,监听到第6步中服务端的数据,收到"HelloClient"。客户端完成,客户端的selector继续轮询事件。
8.服务端:监听到第6步中自己的写事件,取到channel,取消监听写事件,只监听读事件。

核心组件

Channel(通道)

概述

Channel可以理解为通道,通过它可以从不同源(文件/网络等)读取和写入数据(通道是基于Buffer进行读写交互的,因为 Buffer特性所以通道可以异步地读写),因为Channel是全双工的,所以它可以比流更好地映射底层操作系统的APl

分散Scatter && 聚集Gather
  • 分散读取: 将Channel中的数据按照顺序分散到多个Buffer中(即缓冲区数组)
  • 聚集写入: 将多个Buffer(即缓冲区数组)中数据聚集到Channel
实现类

  • FileChannel:主要是用于文件的读写
  • DatagramChannel:主要用于UDP读写网络中的数据
  • SocketChannel:通过TCP读写网络中的数据
  • ServerSocketChannel:主要用于服务端,可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel
Channel与Stream流的区别

Buffer(缓冲区)

概述

Buffer是一个数组对象,我们可以把它理解为临时存储固定数量的写入或者读出的数据的容器.在Java NIO,任何时候访问NIO中的数据都需要通过缓冲区(Buffer)进行操作。读取数据时直接从缓冲区中读取,写入数据时写入至缓冲区

分类
  • 非直接缓冲区: 通过allocate方法将缓冲区分配在JVM内存中
  • 直接缓冲区:通过allocateDirect方法将缓冲区分配在物理内存中,可提高效率
ByteBuffer buf = ByteBuffer.allocate(1024); //创建非直接缓冲区大小为1024
ByteBuffer buffer_direct = ByteBuffer.allocateDirect(1024);//创建直接缓冲区大小为1024
System.out.println("判断是否为直接缓冲区 =" + buffer_direct.isDirect()); //true
子类
Java基本类型都对应着一种Buffer,他们都拥有相同的API, NIO最常用的缓冲区则是ByteBuffer
核心方法
  • allocate:分配一个缓冲区
  • put:存入数据到缓冲区
  • get:获取缓冲区的数据
核心属性
  • capacity:表示缓冲区中最大存储数据的容量,一旦声明不能改变
  • position:表示缓冲区中当前操作数据的位置
    • 写模式下,position表示当前写入的位置,position最大为capacity-1
    • 读模式下,为读入数据的当前位置
  • limit:表示缓冲区中可以操作数据的大小(limit后数据无法读写)
    • 写模式下,写入多少的数据,limit等于多少
    • 读模式下,表示有多少数据可读
  • 0 <= position <= limit <= capacity(始终不变)
    package com.bierce.io;
    import java.nio.ByteBuffer;
    public class TestBuffer{public static void main(String[] args) {ByteBuffer buf = ByteBuffer.allocate(1024); //创建缓冲区大小为1024System.out.println("--------------未写入数据前获取各属性值-------------");System.out.println("position = " + buf.position()); // position = 0System.out.println("limit = " + buf.limit()); //limit = 1024System.out.println("capacity = " + buf.capacity()); //capacity = 1024System.out.println("--------------写入数据后获取各属性值--------------");String data = "data";buf.put(data.getBytes());System.out.println("position = " + buf.position()); // position = 4System.out.println("limit = " + buf.limit()); //limit = 1024System.out.println("capacity = " + buf.capacity()); //capacity = 1024System.out.println("--------------切换到读模式下获取各属性值--------------");buf.flip();buf.put(data.getBytes());System.out.println("position = " + buf.position()); // position = 4System.out.println("limit = " + buf.limit()); //limit = 4System.out.println("capacity = " + buf.capacity()); //capacity = 1024System.out.println("--------------切换到写模式下获取各属性值---------------");buf.flip();System.out.println("position = " + buf.position()); // position = 0System.out.println("limit = " + buf.limit()); //limit = 4System.out.println("capacity = " + buf.capacity()); //capacity = 1024}
    }
    

Selector(选择器)

  • 多路复用器Selector是Java NIO编程的基础,熟练地掌握Selector对于掌握NIO编程至关重要。
  • 多路复用器提供选择已就绪任务的能力,即Selector会不断地轮询注册在其上的Channel,如果某个Channel上面有新的TCP连接接入、读和写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作
  • 一个多路复用器Selector可以同时轮询多个Channel,由于JDK使用了epoll代替传统的select实现,所以它并没有最大连接句柄1024/2048的限制。这也就意味着只需要一个线程负责Selector的轮询,就可以介入成千上万的客户端

Pipe(管道)

概述

Java NIO管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取

示例
Pipe pipe = Pipe.open(); //获取管道
//相当于一个线程写入数据到管道
Pipe.SinkChannel sinkChannel = pipe.sink(); //获取sink管道,用来传送数据
ByteBuffer byteBuffer_write = ByteBuffer.allocate(1024);
byteBuffer_write.put("bierce Never Give up!".getBytes());
byteBuffer_write.flip(); //写入完成后转换为读模式
sinkChannel.write(byteBuffer_write); //通过sink管道发送数据//相当于另一个线程从管道读取数据
Pipe.SourceChannel sourceChannel = pipe.source(); //获取source管道,用来读取数据
ByteBuffer byteBuffer_read = ByteBuffer.allocate(1024);
int length = sourceChannel.read(byteBuffer_read);
System.out.println(new String(byteBuffer_read.array(), 0, length)); //bierce Never Give up!//关闭管道资源
sourceChannel.close();
sinkChannel.close();

适用场景

适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂

AIO(Asynchronous I/O)

概述

AIO也称为NIO2,jdk7后出现的一种异步非阻塞模式,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数(AIO 应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了)

适用场景

JDK7开始支持,适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂

相关文章:

Java IO流(二)IO模型(BIO|NIO|AIO)

概述 Java IO模型同步阻塞IO&#xff08;BIO&#xff09;、同步非阻塞IO&#xff08;NIO&#xff09;、异步非阻塞IO&#xff08;AIO/NIO2&#xff09;,Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装 IO模型 BIO(Blocking I/O) 概述 BIO是一种同步并阻…...

java版本spring cloud 企业工程系统管理 工程项目管理系统源码em

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…...

飞天使-k8s简单搭建

文章目录 k8s概念安装部署-第一版无密钥配置与hosts与关闭swap开启ipv4转发安装前启用脚本开启ip_vs安装指定版本docker 安装kubeadm kubectl kubelet,此部分为基础构建模版 k8s一主一worker节点部署k8s三个master部署,如果负载均衡keepalived 不可用&#xff0c;可以用单节点做…...

java中把一个list转tree的方法

环境 我们有个需求&#xff0c;数据库要存一个无限级联的tree&#xff0c;比如菜单&#xff0c;目录&#xff0c;或者地区等数据&#xff0c;现有两个问题&#xff1a; 问如何设计表。怎么返回给前端一个无线级联的json数据。 思考 第一个问题 在设计表的时候&#xff0c;…...

QT设置widget背景图片

首先说方法&#xff0c;在给widget或者frame或者其他任何类型的控件添加背景图时&#xff0c;在样式表中加入如下代码&#xff0c;指定某个控件&#xff0c;设置其背景。 类名 # 控件名 { 填充方式&#xff1a;图片路径 } 例如&#xff1a; QWidget#Widget {border-image: url…...

【ROS】话题通信--从理论介绍到模型实现(C++)

1.简单介绍 话题通信是ROS中使用频率最高的一种通信模式&#xff0c;话题通信是基于发布订阅模式的&#xff0c;也即:一个节点发布消息&#xff0c;另一个节点订阅该消息。像雷达、摄像头、GPS… 等等一些传感器数据的采集&#xff0c;也都是使用了话题通信&#xff0c;换言之…...

服务器数据恢复-EqualLogic存储RAID5数据恢复案例

服务器数据恢复环境&#xff1a; 一台DELL EqualLogic存储中有一组由16块SAS硬盘组建的RAID5阵列。存储存放虚拟机文件&#xff0c;采用VMFS文件系统&#xff0c;划分了4个lun。 服务器故障&检测&分析&#xff1a; 存储设备上有两个硬盘指示灯显示黄色&#xff0c;存储…...

qsort函数详解

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解qsort函数&#xff0c;如果你觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 一. qsort函数参数详解1.数组首元素地址base2.数组的元素个数num和元素所占内存空间大小w…...

C#学习,委托,事件,泛型,匿名方法

目录 委托 声明委托 实例化委托 委托的多播 委托的用途 事件 通过事件使用委托 声明事件 泛型 泛型的特性 泛型方法 泛型的委托 匿名方法 编写匿名方法的语法 委托 类似于指针&#xff0c;委托是存有对某个方法的引用的一种引用类型变量&#xff0c;引用可以在运…...

2023最新版本~KEIL5使用C++开发STM32

先看效果 开始教学 因为是第一次写这个配置教程 我会尽量详细些 打开一个Keil工程 移除本地core 添加在线core 第一次编译代码 不会有报错 修改main.c文件类型为C 点击魔术棒 把ARM编译器修改为V6 第二次编译会报错语法不兼容 我把汇编部分的这些代码做了…...

汽车领域专业术语

1. DMS/OMS/RMS/IMS DMS&#xff1a;即Driver Monitoring System&#xff0c;监测对象为Driver&#xff08;驾驶员&#xff09;。DMS三大核心&#xff1a; OMS&#xff1a;即Occupancy Monitoring System&#xff0c;监测对象为乘客。 RMS&#xff1a;后排盲区检测系统 IMS&…...

H3C交换机如何配置本地端口镜像并在PC上使用Wireshake抓包

环境: H3C S6520-26Q-SI version 7.1.070, Release 6326 Win 10 专业版 Wireshake Version 4.0.3 问题描述: H3C交换机如何配置本地端口镜像并在PC上使用Wireshake抓包 解决方案: 配置交换机本地端口镜像 1.进入系统视图,并创建本地镜像组1 <H3C>system-vie…...

零基础自学:2023 年的今天,请谨慎进入网络安全行业

前言 2023 年的今天&#xff0c;慎重进入网安行业吧&#xff0c;目前来说信息安全方向的就业对于学历的容忍度比软件开发要大得多&#xff0c;还有很多高中被挖过来的大佬。 理由很简单&#xff0c;目前来说&#xff0c;信息安全的圈子人少&#xff0c;985、211 院校很多都才…...

向gitee推送代码

目录 一、Gitee创建仓库 二、将刚刚创建的仓库放到虚拟机上 2.1 https 方式克隆仓库 2.2 ssh的方式克隆仓库 三、本地开发&#xff0c;推送 3.1 查看是否有远程库 3.2 推送代码 3.3 查看是否推送成功 一、Gitee创建仓库 二、将刚刚创建的仓库放到虚拟机上 2.1 https 方式…...

双指针算法实例1(移动零)

常⻅的双指针有两种形式&#xff1a; 1 对撞指针&#xff08;左右指针&#xff09;&#xff1a; a 对撞指针从两端向中间移动。⼀个指针从最左端开始&#xff0c;另⼀个从最右端开始&#xff0c;然后逐渐往中间逼 近 b 终止条件一般是两指针相遇or错过&#xff08;也可能在循…...

C#程序随系统启动例子 - 开源研究系列文章

今天讲讲C#中应用程序随系统启动的例子。 我们知道&#xff0c;应用程序随系统启动&#xff0c;都是直接在操作系统注册表中写入程序的启动参数&#xff0c;这样操作系统在启动的时候就根据启动参数来启动应用程序&#xff0c;而我们要做的就是将程序启动参数写入注册表即可。此…...

最全攻略之人工智能顶会论文发表

最全攻略之人工智能顶会论文发表 1. 人工智能顶会1.1 CCF 顶会列表2023年人工智能顶会时间线 2.人工智能顶会论文发表流程2.1 顶会论文发表流程2.2 顶会论文审稿流程 3.1顶会论文发表指南3.1 顶会论文七要素3.2 顶会论文写作要点 4.人工智能发展趋势4.1 人工智能未来趋势4.2 人…...

Redis基于内存的key-value结构化NOSQL(非关系型)数据库

Redis Redis介绍Redis的优点Redis的缺点Redis的安装Redis的连接Redis的使用Redis中的数据类型String的使用get setsetex(expire)ttlsetnx(not exit)HashList列表(队列)Set集合ZSet集合Redis 通用命令Redis图形客户端Redis在Java中的使用RedisTemplate...

Spring学习笔记+SpringMvc+SpringBoot学习笔记

壹、核心概念&#xff1a; 1.1. IOC和DI IOC&#xff08;Inversion of Control&#xff09;控制反转&#xff1a;对象的创建控制权由程序转移到外部&#xff0c;这种思想称为控制反转。/使用对象时&#xff0c;由主动new产生对象转换为由外部提供对象&#xff0c;此过程种对象…...

如何在 3Ds Max 中准确地将参考图像调整为正确的尺寸?

您是否想知道如何在 3Ds Max 中轻松直观地调整参考图像的大小&#xff0c;而无需借助第三方解决方案、插件或脚本&#xff1f; 我问自己这个问题&#xff0c;并高兴地发现了FFD Box 2x2x2&#xff0c;我无法停止钦佩这个修改器的多功能性。 在本文中&#xff0c;我想与您分享一…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...