JAVA NIO深入剖析

news2024/11/24 9:20:41

4.1 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 个。

4.2 NIO 和 BIO 的比较

  • BIO 以流的方式处理数据,而 NIO 以块的方式处理数据,块 I/O 的效率比流 I/O 高很多
  • BIO 是阻塞的,NIO 则是非阻塞的
  • BIO 基于字节流和字符流进行操作,而 NIO 基于 Channel(通道)和 Buffer(缓冲区)进行操作,数据总是从通道
    读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择器)用于监听多个通道的事件(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道
NIO BIO
面向缓冲区(Buffer) 面向流(Stream)
非阻塞(Non Blocking IO) 阻塞IO(Blocking IO)
选择器(Selectors)

4.3 NIO 三大核心原理示意图

NIO 有三大核心部分:Channel( 通道) ,Buffer( 缓冲区), Selector( 选择器)

Buffer缓冲区

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

Channel(通道)

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

Selector选择器

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

image-20200619153658139

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

4.4 NIO核心一:缓冲区(Buffer)

缓冲区(Buffer)

一个用于特定基本数据类 型的容器。由 java.nio 包定义的,所有缓冲区 都是 Buffer 抽象类的子类.。Java NIO 中的 Buffer 主要用于与 NIO 通道进行 交互,数据是从通道读入缓冲区,从缓冲区写入通道中的

image-20200619163952309

Buffer 类及其子类

Buffer 就像一个数组,可以保存多个相同类型的数据。根 据数据类型不同 ,有以下 Buffer 常用子类:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

上述 Buffer 类 他们都采用相似的方法进行管理数据,只是各自 管理的数据类型不同而已。都是通过如下方法获取一个 Buffer 对象:

static XxxBuffer allocate(int capacity) : 创建一个容量为capacity 的 XxxBuffer 对象

缓冲区的基本属性

Buffer 中的重要概念:

  • 容量 (capacity) :作为一个内存块,Buffer具有一定的固定大小,也称为"容量",缓冲区容量不能为负,并且创建后不能更改。
  • 限制 (limit):表示缓冲区中可以操作数据的大小(limit 后数据不能进行读写)。缓冲区的限制不能为负,并且不能大于其容量。 写入模式,限制等于buffer的容量。读取模式下,limit等于写入的数据量
  • 位置 (position):下一个要读取或写入的数据的索引。缓冲区的位置不能为 负,并且不能大于其限制
  • 标记 (mark)与重置 (reset):标记是一个索引,通过 Buffer 中的 mark() 方法 指定 Buffer 中一个特定的 position,之后可以通过调用 reset() 方法恢复到这 个 position.
    标记、位置、限制、容量遵守以下不变式: 0 <= mark <= position <= limit <= capacity
  • 图示:
  • image-20200619172434538

Buffer常见方法

  1. Buffer clear() 清空缓冲区并返回对缓冲区的引用
  2. Buffer flip() 为 将缓冲区的界限设置为当前位置,并将当前位置充值为 0
  3. int capacity() 返回 Buffer 的 capacity 大小
  4. boolean hasRemaining() 判断缓冲区中是否还有元素
  5. int limit() 返回 Buffer 的界限(limit) 的位置
  6. Buffer limit(int n) 将设置缓冲区界限为 n, 并返回一个具有新 limit 的缓冲区对象
  7. Buffer mark() 对缓冲区设置标记
  8. int position() 返回缓冲区的当前位置 position
  9. Buffer position(int n) 将设置缓冲区的当前位置为 n , 并返回修改后的 Buffer 对象
  10. int remaining() 返回 position 和 limit 之间的元素个数
  11. Buffer reset() 将位置 position 转到以前设置的 mark 所在的位置
  12. Buffer rewind() 将位置设为为 0, 取消设置的 mark

缓冲区的数据操作

  1. Buffer 所有子类提供了两个用于数据操作的方法:get()put() 方法
  2. 取获取 Buffer

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

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

相关文章

【已解决】Python读取sql数据,报错:Not an executable object,解决方案

【已解决】Python读取sql数据&#xff0c;报错&#xff1a;Not an executable object&#xff0c;解决方案 1.报错内容&#xff1a; 通过Python连接sql&#xff0c;读取sql中数据&#xff0c;报错&#xff1a;Not an executable object。具体代码及报错内容见下&#xff1a; …

为什么mac上有的软件删除不掉?

对于Mac用户来说&#xff0c;软件卸载通常是一个相对简单的过程。然而&#xff0c;有时你可能会发现某些软件似乎“顽固不化”&#xff0c;即使按照常规方式尝试卸载&#xff0c;也依然存在于你的电脑上。这到底是为什么呢&#xff1f;本文将探讨这一问题的可能原因。 1.卸载失…

实用指南:如何解决企业组网中网络卡顿问题?

随着互联网的发展&#xff0c;企业逐步将办公应用系统部署在内网服务器或者上云了&#xff0c;导致很多日常工作都需要网络才能访问。员工在工作的时候网络不给力&#xff0c;卡顿半天也打不开&#xff0c;非常影响工作效率和心情。 在企业组网过程中&#xff0c;网络卡顿现象的…

解决mysql去掉字段空格:中间空格,左侧空格,右侧空格,两端空格,水平制表符(tab键或者\t)空格,换行键(\n)空格,回车键(Enter键)空格

1. 复现错误 今天&#xff0c;查看我禅道上的日志&#xff0c;发现有这个错误&#xff1a; 数据库查询处的字段&#xff0c;存在空格&#xff0c;那么&#xff0c;怎么解决这个问题呢&#xff1f; 2. 解决思路 首先打开控制台&#xff0c;查看所调用的接口。 通过接口找到对应…

线程的概念及使用

1.C11 Thread线程库的使用 本文详细介绍C11 线程库的基本使用&#xff0c;包括如何创建线程、启动线程、等待线程完成、如何分离线程。 创建线程 线程的概念及使用 线程:进程内一个相对独立的、可调度的执行单元&#xff0c;是系统独立调度和分派CPU的基本单位指运行中的程序…

再创佳绩!移远通信RG500U-EA 5G模组获得全球首个紫光展锐V510平台GCF 认证

近日&#xff0c;移远通信工规级5G模组RG500U-EA顺利通过GCF认证&#xff0c;成为全球首款通过该认证的基于紫光展锐V510平台的5G模组。 GCF认证是一种国际性的产品一致性认证&#xff0c;该认证的通过&#xff0c;表明移远通信RG500U-EA模组满足不同运营商的规范要求&#xff…

CUDA学习笔记1——核函数与线程

CUDA安装并配置环境后&#xff0c;使用VS新建工程时会出现对应选项&#xff1a; CUDA核函数调用 CUDA核函数必须用限定词 global 修饰&#xff0c;返回类型必须为void&#xff0c;二者次序随意。函数名与()之间用三括号<<<网格大小&#xff0c;线程块大小>>&…

Visual Studio 2019中的安全问题

最近&#xff0c;在使用Visual Studio 2019的时候遇到了一个很奇怪的问题&#xff0c;如下所示。 这里一直在说scanf函数不安全&#xff0c;导致报错&#xff0c;然后上网查了查相关资料&#xff0c;发现在代码中加那么一句就可以了&#xff0c;而且必须放在最前面。 #define …

网络安全:个人信息保护,企业信息安全,国家网络安全的重要性

在当前的数字化时代&#xff0c;无论是个人&#xff0c;企业&#xff0c;还是国家&#xff0c;都会面临严重的网络安全威胁。网络安全不仅涉及我们的日常生活&#xff0c;也涉及到社会的稳定和国家的安全。这就需要我们高度重视网络安全&#xff0c;强化个人信息保护&#xff0…

HRB系列 电源升压模块直流可调低压升高压输出DC/DC升压变换器

特点 效率高达 80%以上1*2英寸标准封装单电压输出价格低稳压输出工作温度: -40℃~85℃阻燃封装&#xff0c;满足UL94-V0 要求温度特性好可直接焊在PCB 上 应用 HRB W2~40W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&#xff1a;4.5~9V、9~18V、及18~36V、…

Quarto 入门教程 (3):代码框、图形、数据框设置

简介 本文是《手把手教你使用 Quarto 构建文档》第三期&#xff0c;前两期分别介绍了&#xff1a; 第一期 介绍了Quarto 构建文档的原理&#xff1b;可创建的文档类型&#xff1b;对应的参考资源分享。 第二期 介绍了如何使用 Quarto&#xff0c;并编译出文档&#xff08;PDF…

设备管理团队如何做好停机维护工作_基于PreMaint设备数字化平台

在现代工业生产中&#xff0c;设备的正常运行对于企业的生产效率和利润至关重要。而停机维护作为设备管理的重要环节&#xff0c;旨在确保设备的安全性、可靠性和性能稳定。本文将介绍停机维护的概念&#xff0c;讨论如何计划停机维护&#xff0c;并重点探讨如何通过PreMaint设…

Linux 部署项目

部署 Linux 部署项目1. 宝塔部署1.1 前端部署1.2 后端部署 2. docker 部署2.1 后端部署2.2 前端部署 3. 跨域问题3.1 Nginx 代理&#xff08;推荐&#xff09;3.2 修改后端服务3.3 添加 web 全局请求拦截器 4. 域名解析DNSPod添加域名 Linux 部署项目 1. 宝塔部署 准备工作&am…

Kafka消费者群组和负载均衡

前言 在大数据时代&#xff0c;消息处理成为众多企业关注的焦点。而Kafka作为一种高性能、分布式的消息系统&#xff0c;通过其消费者群组和负载均衡的特性&#xff0c;实现了高效的消息处理和可靠的数据传递。 消费者群组 Kafka的消费者群组是一种灵活而强大的机制&#xff…

Java进阶——Java深入学习的笔记汇总 JVM底层、多线程、类加载 ...

前言 spring作为主流的 Java Web 开发的开源框架&#xff0c;是Java 世界最为成功的框架&#xff0c;持续不断深入认识spring框架是Java程序员不变的追求&#xff1b;而spring的底层其实就是Java&#xff0c;因此&#xff0c;深入学习Spring和深入学习Java是硬币的正反面&…

Win10系统打开组策略编辑器的两种方法

组策略编辑器是Win10电脑中很实用的工具&#xff0c;它可以帮助用户管理和设置计算机的安全性、网络连接、软件安装等各种策略。但是&#xff0c;很多新手用户不知道打开Win10电脑中组策略编辑器的方法步骤&#xff0c;下面小编给大家介绍两种简单的方法&#xff0c;帮助打开快…

uniapp EventChannel 页面跳转参数事件传递navigateBack,navigateTo 成功后通知事件区别

问题&#xff1a;navigateBack&#xff08;&#xff09;emit事件在onload()监听不到 从A页面跳转到B页面&#xff0c;在B点击产生数据后&#xff0c;跳转回到A&#xff0c;并告诉A点击的数据是什么&#xff0c;使用&#xff1a; navigateBack&#xff08;&#xff09; B页面&…

内存溢出和内存泄漏

内存溢出和内存泄漏 内存溢出 内存溢出相对于内存泄漏来说&#xff0c;尽管更容易被理解&#xff0c;但是同样的&#xff0c;内存溢出也是引发程序崩溃的罪魁祸首之一。由于GC一直在发展&#xff0c;所以一般情况下&#xff0c;除非应用程序占用的内存增长速度非常快&#xf…

李沐深度学习记录5:13.Dropout

Dropout从零开始实现 import torch from torch import nn from d2l import torch as d2l# 定义Dropout函数 def dropout_layer(X, dropout):assert 0 < dropout < 1# 在本情况中&#xff0c;所有元素都被丢弃if dropout 1:return torch.zeros_like(X)# 在本情况中&…

模拟器运行在AndroidStudio内部,设置其独立窗口显示

在窗口内部运行 设置成独立窗口 Android Studio->Settings或Preferences->Tools->Emulator->取消勾选Launch in the Running Devices tool window --->点击右下角的OK按钮 ---> 重启Android Studio 再次启动模拟器