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参与并发操作,编程比较复杂

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成与设计 Patterson Hennessy 笔记(二)MIPS 指令集

计算机的语言&#xff1a;汇编指令集 也就是指令集。本书主要介绍 MIPS 指令集。 汇编指令 算数运算&#xff1a; add a,b,c # abc sub a,b,c # ab-cMIPS 汇编的注释是 # 号。 由于MIPS中寄存器大小32位&#xff0c;是基本访问单位&#xff0c;因此也被称为一个字 word。M…

汽车领域专业术语

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&…

PHP自己的框架实现config配置层级存取(完善篇二)

1、实现效果 config(include_once $coreConfig); //加载配置文件config() //获取所有配置 config(DB_HOST) 获取配置 2、按层级配置文件加载&#xff0c;存取配置项 config,function.php function config($varNULL,$valueNULL){static $configarray();if(is_array($var)){…

redis Windows版本安装过程(5.0.14)

官网不提供Windows版本的redis安装包&#xff0c;但可以在GitHub网站上找到redis的安装包&#xff1a; Releases tporadowski/redis GitHub &#xff08;相比较Linux其他版本的Redis,Windows版的redis的缺点是版本比较老&#xff0c;官方不提供且不更新&#xff09; 1、zip…

vue使用

详解vue使用Echarts画柱状图_vue.js_脚本之家 Vue修改按钮间距使用 margin-left Vue3 定义变量 &#xff08;没有data了&#xff09; vue3的setup函数中定义data数据&#xff0c;使用data数据_vue3 data_半里_辰昏的博客-CSDN博客 const showFlag ref(false) 修改值&#…

Java源码分析(一)Integer

当你掌握Java语言到了一定的阶段&#xff0c;或者说已经对Java的常用类和API都使用的行云流水。你会不会有一些思考&#xff1f;比如&#xff0c;这个类是如何设计的&#xff1f;这个方法是怎么实现的&#xff1f;接下来的一系列文章&#xff0c;我们一起学习下Java的一些常见类…

【河源源城紫金】IBM 3650 M4服务器主板维修

河源市源城区某财政单位2台IBM System x3650 M4 服务器黄灯故障无法开机&#xff0c;面板报错BOARD黄灯警告&#xff0c;如上图所示&#xff0c;这位客户通过单位朋友介绍&#xff0c;报修2台单位的IBM服务器&#xff0c;冠峰工程师接到客户报修信息后&#xff0c;售后小哥随即…

Linux笔试题(4)

67、在局域网络内的某台主机用ping命令测试网络连接时发现网络内部的主机都可以连同,而不能与公网连通,问题可能是__C_ A.主机ip设置有误 B.没有设置连接局域网的网关 C.局域网的网关或主机的网关设置有误 D.局域网DNS服务器设置有误 解析&#xff1a;在局域网络内的某台主…

WebGL和OpenGL之间的差异

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 WebGL和OpenGL是与图形处理有关的技术标准&#xff0c;它们在计算机图形中扮演着重要的角色。本文将介绍WebGL和OpenGL的区别&#xff0c;并重点介绍"WebGL"和"OpenGL"的特点。 一…

226、仿真-基于51单片机楼道教室走道智能灯光光照人体感应检测控制Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&…

16.3.2 【Linux】程序的管理

程序之间是可以互相控制的。举例来说&#xff0c;你可以关闭、重新启动服务器软件&#xff0c;服务器软件本身是个程序&#xff0c; 你既然可以让她关闭或启动&#xff0c;当然就是可以控制该程序。 使用kill-l或者是man 7 signal可以查询到有多少个signal。主要的讯号代号与名…

当众讲话与演讲口才沙龙活动策划方案

活动名称&#xff1a;当众讲话与演讲口才沙龙 活动目的&#xff1a; 当众讲话与演讲口才沙龙旨在提升参与者的演讲口才能力&#xff0c;培养自信心和表达能力&#xff0c;促进交流与分享。通过举办此活动&#xff0c;我们希望能够帮助参与者克服公众演讲的恐惧&#xff0c;提…

C++ string 的用法

目录 string类string类接口函数及基本用法构造函数&#xff0c;析构函数及赋值重载函数元素访问相关函数operator[]atback和front 迭代器iterator容量操作size()和length()capacity()max_sizeclearemptyreserveresizeshrink_to_fit string类对象修改操作operatorpush_backappen…

【Flink】Flink窗口触发器

数据进入到窗口的时候,窗口是否触发后续的计算由窗口触发器决定,每种类型的窗口都有对应的窗口触发机制。WindowAssigner 默认的 Trigger通常可解决大多数的情况。我们通常使用方式如下,调用trigger()方法把我们想执行触发器传递进去: SingleOutputStreamOperator<Produ…

vue3.0 element-plus 不同版本 el-popover 循环优化

表格内循环el-popover 渲染以后的页面&#xff0c;数据量很大的时候页面会卡&#xff0c;生成的代码&#xff1a; 解决思路&#xff1a;将el-popover提出来&#xff0c;不参与循环&#xff0c;让el-popover只渲染一次 1、以1.1.0-beta.24版为例&#xff08;低版本&#xff09;…

Bigemap Pro国产基础软件介绍——一款多源数据处理软件

一、软件简介 Bigemap Pro是由成都比格图数据处理有限公司(下称”BIGEMAP”)开发和发行的国产大数据处理基础软件。Bigemap Pro是在BIGEMAP GIS Office基础上&#xff0c;经过十年的用户积累与反馈和技术更新迭代出的新一代基础软件产品。Bigemap Pro国产基础软件集成了数据采…

Qt应用开发(基础篇)——高级纯文本窗口 QPlainTextEdit

一、前言 QPlainTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类https://blog.csdn.net/u014491932/article/details/132245486?spm1001.2014.3001.5501框架类QFramehttps://blo…

Python入门【内存管理机制、Python缓存机制、垃圾回收机制、分代回收机制】(三十二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

基于Matlab 代码实现UWB信号的产生和调制、接收和检测系统

文末提供完整的matlab代码实现下载链接 介绍 本文将分为两部分介绍。在第一部分中,使用 TR 的建模UWB 信号发生器,生成编码二进制数据的脉冲调制信号。这第二部分涉及对接收第一部分中生成的信号的接收器进行建模提取并显示信息。每个信号的时间图和频率响应绘制了阶段。使用MA…