首页 > 编程语言 >Java 的 3 种网络编程的I/O 模型

Java 的 3 种网络编程的I/O 模型

时间:2024-01-07 23:02:20浏览次数:35  
标签:Java NIO Buffer 模型 编程 线程 IO 通道

  在Java的软件设计开发中,通信架构不可避免,我们在进行不同系统或者不同进程之间的数据交互,或者在高并发下的通信场景下都需要用到网络通信相关的技术,对于一些经验丰富的程序员来说,Java早期的网络通信架构存在一些缺陷,其中最令人恼火的是基于性能低下的同步阻塞式的I/O通信(BIO),随着互联网开发下通信性能的高要求,Java在2002年开始支持了非阻塞式的I/O通信技术NIO。

1.  I/O 模型基本说明

I/O 模型:就是用什么样的通道或者说是通信模式和架构进行数据的传输和接收,很大程度上决定了程序通信的性能。 Java 共支持 3 种网络编程的I/O 模型:

  • BIO
  • NIO
  • AIO

实际通信需求下,要根据不同的业务场景和性能需求决定选择不同的I/O模型

2. Java BIO

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

Java 的 3 种网络编程的I/O 模型_非阻塞

Java BIO 工作机制

BIO  编程流程的梳理


  1. 服务器端启动一个 ServerSocket,注册端口,调用accpet方法监听客户端的Socket连接。

  1. 客户端启动 Socket 对服务器进行通信,默认情况下服务器端需要对每个客户 建立一个线程与之通讯

    Java 的 3 种网络编程的I/O 模型_Java_02

3. Java NIO

  • Java NIO(New IO)也有人称之为 java non-blocking IO是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。NIO可以理解为非阻塞IO,传统的IO的read和write只能阻塞执行,线程在读写IO期间不能干其他事情,比如调用socket.read()时,如果服务器一直没有数据传输过来,线程就一直阻塞,而NIO中可以配置socket为非阻塞模式。
  • NIO 相关类都被放在 java.nio 包及子包下,并且对原 java.io 包中的很多类进行改写。
  • NIO 有三大核心部分:Channel( 通道) ,Buffer( 缓冲区), Selector( 选择器)
  • Java NIO 的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
  • 通俗理解:NIO 是可以做到用一个线程来处理多个操作的。假设有 1000 个请求过来,根据实际情况,可以分配20 或者 80个线程来处理。不像之前的阻塞 IO 那样,非得分配 1000 个

Java 的 3 种网络编程的I/O 模型_非阻塞_03

NIO 三大核心原理示意图

Buffer缓冲区

缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。相比较直接对数组的操作,Buffer API更加容易操作和管理。

Channel(通道)

Java NIO的通道类似流,但又有些不同:既可以从通道中读取数据,又可以写数据到通道。但流的(input或output)读写通常是单向的。 通道可以非阻塞读取和写入通道,通道可以支持读取或写入缓冲区,也支持异步地读写。

Selector选择器

Selector是 一个Java NIO组件,可以能够检查一个或多个 NIO 通道,并确定哪些通道已经准备好进行读取或写入。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接,提高效率

Java 的 3 种网络编程的I/O 模型_Java_04

  • 每个 channel 都会对应一个 Buffer
  • 一个线程对应Selector , 一个Selector对应多个 channel(连接)
  • 程序切换到哪个 channel 是由事件决定
  • Selector 会根据不同的事件,在各个通道上切换
  • Buffer 就是一个内存块 , 底层是一个数组
  • 数据的读取写入是通过 Buffer完成的 , BIO 中要么是输入流,或者是输出流, 不能双向,但是 NIO 的 Buffer 是可以读也可以写。
  • Java NIO系统的核心在于通道(Channel)和缓冲区 (Buffer)。通道表示打开到 IO 设备(例如:文件、 套接字)的连接。若需要使用 NIO 系统,需要获取 用于连接 IO 设备的通道以及用于容纳数据的缓冲 区。然后操作缓冲区,对数据进行处理。简而言之,Channel 负责传输, Buffer 负责存取数据

Java AIO

Java AIO(NIO.2)异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,一般适用于连接数较多且连接时间较长的应用

与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可, 这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序

BIO、NIO、AIO 适用场景分析

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

标签:Java,NIO,Buffer,模型,编程,线程,IO,通道
From: https://blog.51cto.com/maguobin/9135410

相关文章

  • java后台字符串URLencode、URLdecode及Base64加解密转换
    一、URLencode、URLdecode//将application/x-www-from-urlencoded字符串转换成普通字符串StringkeyWord=URLDecoder.decode("%E4%BD%A0%E5%A5%BD","utf-8");System.out.println(keyWord);//输出你好//将普通字符创转换成application/x-www......
  • Java Steam 常用 API
    微信公众号:运维开发故事作者:wanger现在Java17和Java11基本上可以和Java8平分JDK装机比例。下面是我常用的一些StremAPI操作。除了分组、转换、排序,如果大家还有更多常用的API可以一起留言交流。分组List 默认分组过后是Map<Key,List>List<StreamItem>streamLis......
  • 【教3妹学编程-算法题】赎金信
    3妹:“太阳当空照,花儿对我笑,小鸟说早早早,你为什么背上炸药包”2哥 :3妹,什么事呀这么开森。3妹:2哥你看今天的天气多好啊,最近一周都是大晴天,艳阳高照2哥:是啊,天气不冷不热的,很适合生活3妹:据说南方的小土豆都跑到北方滑雪了,哈哈哈哈2哥:泼水成冰好玩是好玩,但是一定要注意防寒哦,看新闻都......
  • javascript基础学习系列一:标识符
    一般来说,语言中的标识符可以分为两类,一类用于命名语法(以及类型),一类用于命名值(的存储位置)。前者被称为“语法关键字”,后者则被称为“变量”和“常量”。由此引入了一个概念:绑定。从标识符的角度来说,绑定分为语法关键字与语法(语义)逻辑的绑定,以及变量与它所存储值的位置的绑定......
  • Java中DTO和VO的使用指南
    @[TOC]Java中DTO和VO的使用指南在Java开发中,DTO(DataTransferObject)和VO(ValueObject)是两个常见的设计模式,它们在不同的上下文中有着不同的用途。本文将深入讨论DTO和VO的概念、用途以及在实际项目中的使用方法。1.DTO(数据传输对象)DTO是一种用于在不同层之间传递数据的对象,其主要......
  • “华为杯”杭州电子科技大学2023新生编程大赛 1005
    树-HDU7406$xordist(i,j)=xordist(i,k)\oplusxordist(k,j)$在数轴和树上都是成立的那么原式变成$\sum_{i=l}^{r}xordist(i,k)\oplusxordist(k,j)$这里k指定为1号点就变成了一个很简单的拆位考虑贡献的问题了#include<bits/stdc++.h>usingnamespacestd;#de......
  • Java学习网站,哪个最靠谱?
    简介Java学习网站有很多,哪个最靠谱呢?本文对Java学习网站进行对比。第1类:大型培训机构(黑马等)典型机构黑马、尚硅谷、动力节点、白马、千锋、达内。优点知名度高。教程齐全(Java、前端、Python等都有)省心(跟着培训的进度走,不需要自己找资料)缺点学习成本高。(几百到几万不等)。教程质量......
  • Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)
    深度冲突两个模型重叠的模型,通过浏览器旋转预览,会发现模型旋转的时候会发生闪烁。这种情况,主要是两个模型重合,电脑分不清谁在前谁在后,这种情况,可以理解为深度冲突Z-fighting。functionaddBox(){constgeometry=newTHREE.BoxGeometry(10,10,10);//材质constmater......
  • 基于智能手机的行人惯性追踪数据集模型与部署
    论文总结这篇《Smartphone-basedPedestrianInertialTracking:Dataset,Model,andDeployment》论文介绍了一种基于智能手机惯性测量单元(IMU)的行人追踪和定位系统。主要内容和贡献如下:数据集和实验设计:作者开发了一个智能手机惯性测量数据集(SIMD),包含超过4500条步行轨迹,涵盖了......
  • 长见识!!!Java中除了消息队列之外,竟然还能这样实现异步任务
    什么是Java事件在Java中,"event"(事件)通常用于指代一种在特定条件下触发的通知或者信号。在Java编程中,事件代表着程序中发生的某种动作或改变,例如用户的交互操作、状态的转换,或者其他外部因素触发的通知。Java中的事件通常与事件监听器(EventListener)和事件处理器(EventHandler)一起使......