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
子类
核心方法
- 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(BIO)、同步非阻塞IO(NIO)、异步非阻塞IO(AIO/NIO2),Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装 IO模型 BIO(Blocking I/O) 概述 BIO是一种同步并阻…...
java版本spring cloud 企业工程系统管理 工程项目管理系统源码em
工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典ÿ…...
飞天使-k8s简单搭建
文章目录 k8s概念安装部署-第一版无密钥配置与hosts与关闭swap开启ipv4转发安装前启用脚本开启ip_vs安装指定版本docker 安装kubeadm kubectl kubelet,此部分为基础构建模版 k8s一主一worker节点部署k8s三个master部署,如果负载均衡keepalived 不可用,可以用单节点做…...
java中把一个list转tree的方法
环境 我们有个需求,数据库要存一个无限级联的tree,比如菜单,目录,或者地区等数据,现有两个问题: 问如何设计表。怎么返回给前端一个无线级联的json数据。 思考 第一个问题 在设计表的时候,…...
QT设置widget背景图片
首先说方法,在给widget或者frame或者其他任何类型的控件添加背景图时,在样式表中加入如下代码,指定某个控件,设置其背景。 类名 # 控件名 { 填充方式:图片路径 } 例如: QWidget#Widget {border-image: url…...
【ROS】话题通信--从理论介绍到模型实现(C++)
1.简单介绍 话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。像雷达、摄像头、GPS… 等等一些传感器数据的采集,也都是使用了话题通信,换言之…...
服务器数据恢复-EqualLogic存储RAID5数据恢复案例
服务器数据恢复环境: 一台DELL EqualLogic存储中有一组由16块SAS硬盘组建的RAID5阵列。存储存放虚拟机文件,采用VMFS文件系统,划分了4个lun。 服务器故障&检测&分析: 存储设备上有两个硬盘指示灯显示黄色,存储…...
qsort函数详解
大家好,我是苏貝,本篇博客带大家了解qsort函数,如果你觉得我写的不错的话,可以给我一个赞👍吗,感谢❤️ 文章目录 一. qsort函数参数详解1.数组首元素地址base2.数组的元素个数num和元素所占内存空间大小w…...
C#学习,委托,事件,泛型,匿名方法
目录 委托 声明委托 实例化委托 委托的多播 委托的用途 事件 通过事件使用委托 声明事件 泛型 泛型的特性 泛型方法 泛型的委托 匿名方法 编写匿名方法的语法 委托 类似于指针,委托是存有对某个方法的引用的一种引用类型变量,引用可以在运…...
2023最新版本~KEIL5使用C++开发STM32
先看效果 开始教学 因为是第一次写这个配置教程 我会尽量详细些 打开一个Keil工程 移除本地core 添加在线core 第一次编译代码 不会有报错 修改main.c文件类型为C 点击魔术棒 把ARM编译器修改为V6 第二次编译会报错语法不兼容 我把汇编部分的这些代码做了…...
汽车领域专业术语
1. DMS/OMS/RMS/IMS DMS:即Driver Monitoring System,监测对象为Driver(驾驶员)。DMS三大核心: OMS:即Occupancy Monitoring System,监测对象为乘客。 RMS:后排盲区检测系统 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 年的今天,慎重进入网安行业吧,目前来说信息安全方向的就业对于学历的容忍度比软件开发要大得多,还有很多高中被挖过来的大佬。 理由很简单,目前来说,信息安全的圈子人少,985、211 院校很多都才…...
向gitee推送代码
目录 一、Gitee创建仓库 二、将刚刚创建的仓库放到虚拟机上 2.1 https 方式克隆仓库 2.2 ssh的方式克隆仓库 三、本地开发,推送 3.1 查看是否有远程库 3.2 推送代码 3.3 查看是否推送成功 一、Gitee创建仓库 二、将刚刚创建的仓库放到虚拟机上 2.1 https 方式…...
双指针算法实例1(移动零)
常⻅的双指针有两种形式: 1 对撞指针(左右指针): a 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼 近 b 终止条件一般是两指针相遇or错过(也可能在循…...
C#程序随系统启动例子 - 开源研究系列文章
今天讲讲C#中应用程序随系统启动的例子。 我们知道,应用程序随系统启动,都是直接在操作系统注册表中写入程序的启动参数,这样操作系统在启动的时候就根据启动参数来启动应用程序,而我们要做的就是将程序启动参数写入注册表即可。此…...
最全攻略之人工智能顶会论文发表
最全攻略之人工智能顶会论文发表 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学习笔记
壹、核心概念: 1.1. IOC和DI IOC(Inversion of Control)控制反转:对象的创建控制权由程序转移到外部,这种思想称为控制反转。/使用对象时,由主动new产生对象转换为由外部提供对象,此过程种对象…...
如何在 3Ds Max 中准确地将参考图像调整为正确的尺寸?
您是否想知道如何在 3Ds Max 中轻松直观地调整参考图像的大小,而无需借助第三方解决方案、插件或脚本? 我问自己这个问题,并高兴地发现了FFD Box 2x2x2,我无法停止钦佩这个修改器的多功能性。 在本文中,我想与您分享一…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

