Java IO模型BIO、NIO、AIO介绍

第一章 BIO、NIO、AIO课程介绍

1.1 课程说明

  在java的软件设计开发中,通信架构是不可避免的,我们在进行不同系统或者不同进程之间的数据交互,或者在高并发下的通信场景下都需要用到网络通信相关的技术,对于一些经验丰富的程序员来说,Java早期的网络通 信架构存在一些缺陷,其中最令人恼火的是基于性能低下的同步阻塞式的I/O通信(BIO),随着互联网开发下通 信性能的高要求,Java在2002年开始支持了非阴塞式的I/O通信技术(NIO)。
  大多数读者在学习网络通信相关技术的 时候,都只是接触到零碎的通信技术点,没有完整的技术体系架构,以至于对Java的通信场景总是没有清晰的解决方案。本次课程将通过大量清晰直接的案例从最基础的BlO式通信开始介绍到NIO、AIO,读者可以清晰的了解到阻塞、同步、异步的现象、概念和特征以及优缺点。本课程结合了大量的案例让读者可以快速了解每种通信架构的使用。

1.2 本课程学习要求

  • 本课程不太适合完全0基础学员
  • 至少需要掌握:java SE基础编程,如java多线程,java IO流编程,java网络基础知识(如:IP,端口,协议),常用的Java设计模式要有一定的了解。
  • 能熟练掌握Java OOP编程,有一定的编程思维。

1.3 通信技术整体解决的问题

  • 局域网内的通信要求
  • 多系统间的底层消息传递机制
  • 高并发下,大数据量的通信场景需要,如netty
  • 游戏行业,无论是手游服务端,还是大型的网络游戏,java语言都得到越来越广泛的应用

第二章 Java的I/O演进之路

2.1 I/O模型基本说明

I/O模型:就是用什么样的通道或者说是通信模式和架构进行数据的传输和接收,很大程度上决定了程序通信的性能 , Java共支持3种网络编程的I/O模型:BlO. NIO. AlO
实际通信需求下,要根据不同的业务场景和性能需求决定选择不同的I/O模型

2.2 I/O模型

Java BIO
同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销【简单示意图 】
在这里插入图片描述
java NIO
Java NIO:同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理【简单示意图】
在这里插入图片描述
java AIO
java AIO(NIO.2):异步异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完 成了再通知服务器应用去启动线程进行处理,一般适用于连接数较多且连接时间较长的应用

2.3 BIO、NIO、AIO适用场景分析

1、 BIO方式适用于连接数目比小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用
中, jDK1.4以前的唯一选择,但程序简单易理解。
2、 NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器
间通讯等。 编程比较复杂,jDK1 .4开始支持。
3、 AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并
发操作, 编程比较复杂,JDK7开始支持。

第三章 JAVA BIO深入剖析

3.1 Java BIO基本介绍

  • Java BlO就是传统的Java IO编程,其相关的类和接口在Java.io 包中
  • BIO(blocking I/O)同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器).

3.2 java BIO工作机制

在这里插入图片描述

#3.3 传统的BIO编程实例回顾

  网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定IP地址和端口),客户端通过连接操作向服务端监听的端口地址发起连接请求,基于TCP协议下进行三次握手连接,连接成功后,双方通过网络套接字(Socket)进行通信。
  传统的同步阻塞模型开发中,服务端ServerSocket负责绑定IP地址,启动监听端口;客户端Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。
  基于BIO模式下的通信,客户端-服务端是完全同步,完全藕合的。
服务端案例如下:

/*** 目标:客户端发送消息,服务端接收消息*/
public class Server {public static void main(String[] args) {try {System.out.println("===服务端启动===");//1.定义一个ServerSocket对象进行服务端的端口注册ServerSocket ss = new ServerSocket(9999);//2. 监听客户端的Socket连接请求Socket socket = ss.accept();//3.从socket管道中得到一个字节输入流对象InputStream is = socket.getInputStream();//4.把字节输入流包装成一个缓存字符输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));String msg;/*while ((msg = br.readLine()) != null){System.out.println("服务端接收到:" + msg);}*/if ((msg = br.readLine()) != null){System.out.println("服务端接收到:" + msg);}} catch (IOException e) {e.printStackTrace();}}
}

客户端案例如下:

/**
* 客户端
*/
public class Client {public static void main(String[] args) {try {//1.创建Socket对象请求服务端的连接Socket socket = new Socket("127.0.0.1",9999);//2.从Socket对象中获取一个字节输出流OutputStream os = socket.getOutputStream();//3.把字节输出流包装成一个打印流PrintStream ps = new PrintStream(os);//ps.print("hello World! 服务端,你好");ps.println("hello World! 服务端,你好");ps.flush();} catch (IOException e) {e.printStackTrace();}}
}

输出:

===服务端启动===
服务端接收到:hello World! 服务端,你好

小结

  • 在以上通信中,服务端会一直等待客户端的消息,如果客户端没有进行消息的发送,服务端将一直进入阻塞状态
  • 同时服务端是按照行获取消息的,这意味着客户端也必须按照行进行消息的发送,否则服务端将进入等待消息的阻塞状态!

3.4 BIO模式下多发和多收消息

在上面的案例中,只能实现客户端发送消息,服务端接收消息,并不能实现反复的收消息和反复的发消息,我们只需要在客户端案例中,加上反复按照行发送消息的逻辑即可! 案例代码如下:
服务端代码如下

/**
* 目标:服务端可以反复的接收消息,客户端可以反复的发送消息
*/
public class Server {public static void main(String[] args) {try {System.out.println("===服务端启动===");//1.定义一个ServerSocket对象进行服务端的端口注册ServerSocket ss = new ServerSocket(9999);//2. 监听客户端的Socket连接请求Socket socket = ss.accept();//3.从socket管道中得到一个字节输入流对象InputStream is = socket.getInputStream();//4.把字节输入流包装成一个缓存字符输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));String msg;while ((msg = br.readLine()) != null){System.out.println("服务端接收到:" + msg);}} catch (IOException e) {e.printStackTrace();}}
}

客户端代码如下

/**
* 客户端
*/
public class Client {public static void main(String[] args) {try {//1.创建Socket对象请求服务端的连接Socket socket = new Socket("127.0.0.1",9999);//2.从Socket对象中获取一个字节输出流OutputStream os = socket.getOutputStream();//3.把字节输出流包装成一个打印流PrintStream ps = new PrintStream(os);Scanner sc = new Scanner(System.in);while (true){System.out.print("请说:");String msg = sc.nextLine();ps.println(msg);ps.flush();}} catch (IOException e) {e.printStackTrace();}}
}

输入输出:

客户端:
请说:hello
请说:what are you doing?
请说:
服务端:
===服务端启动===
服务端接收到:hello
服务端接收到:what are you doing?

3.5 BIO模式下接收多个客户端

概述
在上述的案例中,一个服务端只能接收一个客户端的通信请求,那么如果服务端需要处理很多个客户端的消息通信请求应该如何处理呢,此时我们就需要在服务端引入线程了,也就是说客户端每发起一个请求,服务端就创建一个新的线程来处理这个客户端的请求,这样就实现了一个客户端一个线程的模型,图解模式如下:
在这里插入图片描述

未完待续。。。。

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

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

相关文章

Windows桌面运维----第四天

1、U盘故障打不开: 操作方式:WinR打开运行,输入cmd确定,在(C:\Users\Administrator>)后输入chkdsk,空格,输入U盘盘符,例如F:/F,回车,等待修复完成。 2、…

自然语言处理概述

目录 1.概述 2.背景 3.作用 4.优缺点 4.1.优点 4.2.缺点 5.应用场景 5.1.十个应用场景 5.2.文本分类 5.2.1.一般流程 5.2.2.示例 6.使用示例 7.总结 1.概述 自然语言处理(NLP)是计算机科学、人工智能和语言学的交叉领域,旨在实…

Redis 主从同步

主从同步 很多企业没有使用Redis的集群,但是至少都做了主从。有了主从,当master挂掉的时候,运维让从库过来接管,服务就可以继续,否则master需要经过数据恢复和重启的过程,可能会拖很长时间,影响…

Git pull下来时合并分支

执行git pull时报错如下 解决方法: VSCode git中手动选取分支,完成合并 git add .; git commit -m “resolve”git push -u origin main

Java零基础之多线程篇:线程的多种创建方式

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…

如何配置taro

文章目录 step1. 全局安装wepacksetp2. 使用npm安装tarostep3. 项目初始化 使用taro时需要在本地配置好nodejs环境,关于如何配置nodejs可参考我的这篇博文 如何配置nodejs环境 step1. 全局安装wepack 使用指令npm install webpack -g即可 安装完成后可看到有wepa…

Socket 原理和思考

众所周知Reactor是一种非常重要和应用广泛的网络编程模式,而Java NIO是Reactor模式的一个具体实现,在Netty和Redis都有对其的运用。而不管上层模式如何,底层都是走的Socket,对底层原理的了解会反哺于上层,避免空中楼阁…

前端 JS 经典:数字变化动画

1. 需求 给你一个数字,当这个数字变化时,有一个动画的过渡效果。 2. 思路 首先我们要知道两个数字变化需要多少秒,然后变化的范围,算出变化的速度。记住开始变化的时间,然后通过 requestAnimationFrame 函数&#x…

centos 7.8 安装sql server 2019

1.系统环境 centos 7.8 2.数据库安装文件准备 下载 SQL Server 2019 (15.x) Red Hat 存储库配置文件 sudo curl -o /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/7/mssql-server-2019.repo 采用yum源进行不安装下载,这时yum 会自动检测…

算法竞赛数论杂题

menji 和 gcd 题目: 一开始以为是只有l不确定,r是确定的,这样的话我们可以枚举r的所有约数,然后对其每个约数x进行判断,判断是否满足题意,具体做法是先让l % x如果 0则该约数可行,如果不可行…

【机器学习】:线性回归模型学习路线

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 💥💥个人主页:奋斗的小羊 💥💥所属专栏:C语言 🚀本系列文章为个人学习…

教你python自动识别图文验证码的解决方案!

验证码识别解决方案 对于web应用程序来讲,处于安全性考虑,在登录的时候,都会设置验证码,验证码的类型种类繁多,有图片中辨别数字字母的,有点击图片中指定的文字的,也有算术计算结果的&#xff0…

成都爱尔李晓峰主任讲解眼角多出一层“膜”是什么?怎么治

眼角边突然发现长出来一层皮一层膜一样的东西,肉色挡在眼白上呈三角形,这到底是什么? 一种常见眼科疾病“翼状胬肉”,因其形状像昆虫的翅膀而得名的,它是受外界剌激而引起的一种慢性炎症性病变。 覆盖在眼睛表面的那…

JUC并发编程第十三章——读写锁、邮戳锁

本章路线总纲 无锁——>独占锁——>读写锁——>邮戳锁 1 关于锁的面试题 你知道Java里面有那些锁你说说你用过的锁,锁饥饿问题是什么?有没有比读写锁更快的锁StampedLock知道吗?(邮戳锁/票据锁)ReentrantR…

使用自定义注解进行权限校验

一,前言 对于一些重复性的操作我们可以用提取为util的方式进行处理,但也可以更简便一些,比如自定义个注解进行。选择看这篇文章的小伙伴想必都对注解不陌生,但是可能对它的工作原理不太清楚。这里我们用注解实现对接口的权限校验…

Wireshark v4 修改版安装教程(免费开源的网络嗅探抓包工具)

前言 Wireshark(前称Ethereal)是一款免费开源的网络嗅探抓包工具,世界上最流行的网络协议分析器!网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark网络抓包工具使用WinPCAP作为…

基于GWO-CNN-LSTM数据时间序列预测(多输入单输出)-多维时间序列模型-MATLAB实现

基于GWO-CNN-LSTM数据时间序列预测(多输入单输出)-多维时间序列模型-MATLAB实现 基于灰狼优化(Grey Wolf Optimizer, GWO)、卷积神经网络(Convolutional Neural Network, CNN)和长短期记忆网络(Long Short-Term Memor…

【计算机视觉(11)】

基于Python的OpenCV基础入门——图像梯度变换 图像梯度变换Sobel算子Scharr算子Laplacian算子 图像梯度变换的代码实现以及效果图 图像梯度变换 图像梯度变换可以用于边缘检测、特征提取、增强图像和压缩图像等多种任务。图图像梯度可以把图像看成二维离散函数,图像…

什么是进程?

目录 进程 进程的特征, 概念 我们下面先简单介绍一下什么是进程 接下来看看一个程序的运行过程 进程的组成 进程的状态和转换 进程的状态 进程状态的转换 ​编辑 进程的组织方式 进程控制 如何实现进程控制 为什么进程控制的过程需要一气呵成? 进程控制的实现…

前端初学java

目录 java术语 JDK Javac Java Jdb Jhat JVM JRE JAR JDK下载 运行java文件 字面量 隐式转换 强制转换 注意 运算符 &&、||、&、| Switch 程序入口 String[] args 数组 静态初始化 动态初始化 变量初始化 Java内存 方法 重载 Final 包 …