上海部道网站 建设/手机网站建设

上海部道网站 建设,手机网站建设,高质量的猎建筑人才,网站收录多少才有排名IO和NIO的区别: IO:通过流处理数据,仅支持阻塞IO。 核心组件:InputStream /OutputStream用于字节的读写,Reader / Writer:用于字符流的读写。读取过程中无法被中断,是阻塞式IO。 NIO:通过管道处…

IO和NIO的区别:

  1. IO:通过流处理数据,仅支持阻塞IO。
    核心组件:InputStream /OutputStream用于字节的读写,Reader / Writer:用于字符流的读写。读取过程中无法被中断,是阻塞式IO。
  2. NIO:通过管道处理数据,支持阻塞IO和非阻塞IO。
    核心组件:Channel通道、Buffer缓冲区、Selector选择器。Channel与Buffer做直接交互,用于数据的传输,支持非阻塞IO,Buffer用于存放数据,Selector用于管理多个管道,允许单个线程处理多个IO。


NIO三大核心组件

NIO由三大核心组件分别是:Channel管道、Buffer缓冲区、Selector选择器。

Channel

  • 作用:替代传统I/O中的流(Stream),支持双向数据传输(读/写),直接与缓冲区(Buffer)交互。

  • 特点

    • 非阻塞模式(可通过configureBlocking(false)设置)。

    • 操作基于缓冲区,效率更高。

  • 常见实现类

    • FileChannel:文件I/O。

    • SocketChannel / ServerSocketChannel:TCP网络通信。

    • DatagramChannel:UDP网络通信。

Buffer

  • 作用:临时存储数据的容器,是Channel读写数据的直接目标。

  • 核心属性

    • capacity:最大容量。

    • position:当前操作位置。

    • limit:可操作数据的上限。

    • mark:标记位置(用于reset())。

  • 常见类型

    • ByteBuffer(最常用)、CharBufferIntBuffer等。

  • 关键操作

    • put()/get():读写数据。

    • flip():切换为读模式。

    • clear()/compact():清空或压缩缓冲区。

Selector

  • 作用:监听多个Channel的事件(如连接就绪、读就绪、写就绪),实现单线程管理多通道的高并发I/O。

  • 核心机制

    • 基于事件驱动的SelectionKey(包含事件类型和对应的Channel)。

    • 底层依赖操作系统的epoll(Linux)或kqueue(Mac)等系统调用。

  • 使用步骤

    1. 创建Selector:Selector.open()

    2. 将Channel注册到Selector,指定监听事件(如SelectionKey.OP_READ)。

    3. 调用select()方法阻塞等待就绪事件。

    4. 通过selectedKeys()处理就绪的Channel。

 Selector 的 4 种监听事件

事件说明适用 Channel
SelectionKey.OP_ACCEPT服务端接收新连接ServerSocketChannel
SelectionKey.OP_CONNECT客户端连接完成SocketChannel
SelectionKey.OP_READ数据可读SocketChannel / DatagramChannel
SelectionKey.OP_WRITE数据可写SocketChannel / DatagramChannel

Channel与Buffer联调

阻塞IO案例

ServerSocketChannel.accept():该方法用于等待客户端连接,直到有客户端连接才会返回,如果没有客户端连接则会一直阻塞。

SocketChannel.read(ByteBuffer):改方法用于接收客户端的数据,直到有数据才会返回,否则将一直阻塞线程。

    package com.jiawa.netty.server;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.List;import static com.jiawa.netty.utils.ByteBufferUtil.debugAll;public class Server {private static final Logger logger = LoggerFactory.getLogger(Server.class);public static void main(String[] args) throws IOException {//创建缓存、缓存客户端信息ByteBuffer buffer = ByteBuffer.allocate(16);//创建服务器ServerSocketChannel server = ServerSocketChannel.open();//绑定端口server.bind(new InetSocketAddress(8080));//创建客户端存储集合List<SocketChannel> clients = new java.util.ArrayList<>();//接收客户端while (true) {//阻塞线程,直到有客户端请求连接后释放SocketChannel client = server.accept();//如果有客户端请求,则返回客户端信息logger.info("收到客户端请求:{}", client);clients.add(client);for (SocketChannel c : clients) {//读取客户端数据int read = c.read(buffer);if (read > 0) {logger.info("读取客户端数据:{}", read);//打开读buffer.flip();//打印数据debugAll(buffer);//清空buffer.clear();}}}}}

非阻塞IO案例

server.configureBlocking(false):将 ServerSocketChannel 设置为非阻塞模式。

client.configureBlocking(false):将每个 SocketChannel 设置为非阻塞模式。

设置为非阻塞之后,则不会阻塞线程,不管是否有客户端连接或者接收客户端数据,都会直接返回,不会阻塞线程。

package com.jiawa.netty.server;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.List;import static com.jiawa.netty.utils.ByteBufferUtil.debugAll;public class Server {private static final Logger logger = LoggerFactory.getLogger(Server.class);public static void main(String[] args) throws IOException {//创建缓存、缓存客户端信息ByteBuffer buffer = ByteBuffer.allocate(16);//创建服务器ServerSocketChannel server = ServerSocketChannel.open();//非阻塞if (server!= null){server.configureBlocking(false);}//绑定端口server.bind(new InetSocketAddress(8080));//创建客户端存储集合List<SocketChannel> clients = new java.util.ArrayList<>();//接收客户端while (true) {//阻塞线程,直到有客户端请求连接后释放SocketChannel client = server.accept();//将客户端设置为非阻塞if (client != null) {client.configureBlocking(false);}//如果有客户端请求,则返回客户端信息if (client != null) {logger.info("收到客户端请求:{}", client);clients.add(client);}for (SocketChannel c : clients) {//读取客户端数据int read = c.read(buffer);if (read > 0){logger.info("读取客户端数据:{}", read);//打开读buffer.flip();//打印数据debugAll(buffer);//清空buffer.clear();}}}}
}

Channel、Buffer、Selector案例

package com.example.demo.server;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;public class NioServer {public static void main(String[] args) throws IOException {// 创建一个Selector对象,用于管理多个通道的事件Selector selector = Selector.open();// 创建一个ServerSocketChannel对象,用于监听客户端连接请求ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 绑定服务器套接字到本地地址和端口8080serverSocketChannel.bind(new InetSocketAddress(8080));// 设置ServerSocketChannel为非阻塞模式serverSocketChannel.configureBlocking(false);// 将ServerSocketChannel注册到Selector上,并监听ACCEPT事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器启动,等待客户端连接...");// 无限循环,持续处理客户端连接和数据读取while (true) {// 阻塞等待感兴趣的事件发生(如新的连接或可读的数据)int readyChannels = selector.select();// 如果没有准备好的通道,则继续下一次循环if (readyChannels == 0) continue;// 获取所有准备就绪的SelectionKey迭代器Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();// 遍历所有准备就绪的SelectionKeywhile (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 检查是否是新的连接请求if (key.isAcceptable()) {// 处理新的连接请求ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 接受新的客户端连接SocketChannel sc = ssc.accept();// 设置新连接的SocketChannel为非阻塞模式sc.configureBlocking(false);// 将新连接的SocketChannel注册到Selector上,并监听READ事件sc.register(selector, SelectionKey.OP_READ);System.out.println("新的客户端已连接"); // 打印连接信息} else if (key.isReadable()) {// 处理可读事件SocketChannel sc = (SocketChannel) key.channel();// 分配一个新的ByteBuffer,大小为1024字节ByteBuffer buffer = ByteBuffer.allocate(1024);// 从SocketChannel读取数据到ByteBuffer中int bytesRead = sc.read(buffer);// 如果读取到-1,表示客户端断开连接if (bytesRead == -1) {sc.close(); // 关闭SocketChannelSystem.out.println("客户端断开连接"); // 打印断开信息} else {// 切换ByteBuffer到读模式buffer.flip();// 读取ByteBuffer中的数据到byte数组byte[] bytes = new byte[buffer.remaining()];buffer.get(bytes);// 将byte数组转换为字符串String message = new String(bytes);System.out.println("收到消息: " + message); // 打印接收到的消息}}// 移除已经处理过的SelectionKeykeyIterator.remove();}}}
}

Channel常用方法:

1. 通用方法(所有Channel实现类共有)

方法说明
boolean isOpen()判断通道是否处于打开状态。
void close()关闭通道,释放资源(必须显式调用,否则可能泄漏资源)。
boolean isConnected()(仅Socket相关Channel)检查通道是否已连接。

2. 可读/可写操作

方法说明
int read(ByteBuffer dst)从通道读取数据到缓冲区,返回实际读取的字节数(非阻塞模式下可能返回0)。
int write(ByteBuffer src)将缓冲区数据写入通道,返回实际写入的字节数(非阻塞模式下可能返回0)。

3. 非阻塞模式控制

方法说明
void configureBlocking(boolean block)设置通道是否为阻塞模式(true为阻塞,false为非阻塞)。
boolean isBlocking()检查通道当前是否为阻塞模式。

4. 网络Channel特有方法(SocketChannel/ServerSocketChannel)

方法说明
SocketChannel bind(SocketAddress local)绑定通道到本地地址(用于服务端)。
SocketAddress getLocalAddress()获取绑定的本地地址。
SocketChannel connect(SocketAddress remote)连接到远程地址(客户端)。
boolean finishConnect()完成非阻塞连接(需配合connect()使用)。
SocketChannel accept()(仅ServerSocketChannel)接受客户端连接,返回一个新的SocketChannel

5. FileChannel特有方法

方法说明
long position()获取当前文件指针位置。
FileChannel position(long newPosition)设置文件指针位置。
long size()返回文件大小。
FileChannel truncate(long size)截断文件到指定大小。
int read(ByteBuffer dst, long position)从文件指定位置读取数据(不移动指针)。
int write(ByteBuffer src, long position)向文件指定位置写入数据(不移动指针)。
long transferTo(long position, long count, WritableByteChannel target)将数据从文件通道直接传输到目标通道(零拷贝优化)。
long transferFrom(ReadableByteChannel src, long position, long count)从源通道直接接收数据到文件通道(零拷贝优化)。
void force(boolean metaData)强制将数据刷到磁盘(确保写入持久化)。

6. DatagramChannel特有方法(UDP)

方法说明
DatagramChannel bind(SocketAddress local)绑定到本地端口。
SocketAddress receive(ByteBuffer dst)接收UDP数据包,返回发送方地址。
int send(ByteBuffer src, SocketAddress target)发送UDP数据包到目标地址。

Buffer常用方法

1. 核心属性相关方法

方法作用说明
int capacity()返回缓冲区容量创建后不可变
int position()返回当前操作位置下一个读写操作的索引
Buffer position(int newPosition)设置当前位置需满足 0 ≤ position ≤ limit
int limit()返回可操作数据上限缓冲区有效数据边界
Buffer limit(int newLimit)设置新的上限需满足 0 ≤ limit ≤ capacity
Buffer mark()标记当前位置配合reset()回溯
Buffer reset()恢复到标记位置未调用mark()会抛异常

2. 模式切换方法

方法作用说明
Buffer flip()写模式 → 读模式limit设为当前positionposition归零
Buffer clear()读模式 → 写模式position=0limit=capacity不清空数据
Buffer rewind()重置为读模式起点position=0limit不变(重复读)
boolean hasRemaining()检查剩余可操作数据return position < limit
int remaining()返回剩余可操作数据量return limit - position

3. 数据读写方法

通用方法(所有Buffer子类)
方法作用
T get()读取当前位置的数据并移动position
Buffer put(T value)写入数据到当前位置并移动position
T get(int index)读取指定位置数据(不移动position
Buffer put(int index, T value)写入数据到指定位置(不移动position
ByteBuffer特有方法
方法作用
byte[] array()返回底层字节数组(仅非直接缓冲区有效)
ByteBuffer put(byte[] src)批量写入字节数组
ByteBuffer get(byte[] dst)批量读取到字节数组
ByteBuffer slice()创建共享底层数据的新缓冲区(切片)
ByteBuffer duplicate()创建完全独立的副本缓冲区

4. 压缩与填充

方法作用典型场景
Buffer compact()压缩缓冲区将未读数据移到起始位置,position指向剩余空间
Buffer fill(byte value)(非标准API,需自行实现)填充固定值到缓冲区

5. 直接缓冲区控制(ByteBuffer特有)

方法作用
static ByteBuffer allocateDirect(int capacity)创建直接缓冲区(堆外内存)
boolean isDirect()判断是否为直接缓冲区

Selector 的常用方法

(1)Selector 的创建与关闭

方法说明
Selector.open()创建 Selector
boolean isOpen()检查 Selector 是否打开
void close()关闭 Selector(释放资源)

(2)Channel 的注册与注销

方法说明
channel.register(selector, ops)注册 Channel 到 Selector,并指定监听事件
key.cancel()取消 Channel 的注册(不会立即注销,需调用 select() 后生效)

(3)事件监听

方法说明
int select()阻塞等待至少一个事件就绪(返回就绪的 Channel 数量)
int select(long timeout)带超时的阻塞等待
int selectNow()非阻塞检查(立即返回)
Set<SelectionKey> selectedKeys()获取所有就绪的事件(需手动处理并移除)
Set<SelectionKey> keys()获取所有已注册的 Channel(包括未就绪的)

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

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

相关文章

基于vue.js开发的家庭装修管理系统开发与设计(源码+lw+部署文档+讲解),源码可白嫖!

摘要 本家庭装修管理系统采用B/S架构&#xff0c;数据库是MySQL&#xff0c;网站的搭建与开发采用了先进的Node.js语言进行编写&#xff0c;使用了VUE框架。该系统从两个对象&#xff1a;由管理员和用户来对系统进行设计构建。用户的功能包括&#xff1a;注册、登录、浏览首页…

OpenCV图像拼接(5)图像拼接模块的用于创建权重图函数createWeightMap()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::createWeightMap 是 OpenCV 库中用于图像拼接模块的一个函数&#xff0c;主要用于创建权重图。这个权重图在图像拼接过程中扮演着重…

LangGraph 怎么控制递归次数

这一节我们讲讲langgraph图的递归限制 Recursion Limit&#xff0c;递归限制设置了图在单次执行过程中可以执行的最大超级步骤数。一旦达到该限制&#xff0c;LangGraph 将引发 GraphRecursionError 错误。默认情况下&#xff0c;此值设置为 25 步。递归限制可以在运行时为任何…

Milvus WeightedRanker 对比 RRF 重排机制

省流:优先选择WeightedRanker 以rag为例,优先选择bm25全文检索,其次选择向量检索 Milvus混合搜索中的重排机制 Milvus通过hybrid_search() API启用混合搜索功能&#xff0c;结合复杂的重排策略来优化多个AnnSearchRequest实例的搜索结果。本主题涵盖了重排过程&#xff0c;…

在K8S中使用ArgoCD做持续部署

一、了解argocd ArgoCD是一个基于Kubernetes的GitOps持续交付工具&#xff0c;应用的部署和更新都可以在Git仓库上同步实现&#xff0c;并自带一个可视化界面。本文介绍如何使用GitArgocd方式来实现在k8s中部署和更新应用服务。关于ci这一块这里不多介绍。主要讲解argocd如何实…

可视化图解算法:删除有序(排序)链表中重复的元素

1. 题目 描述 删除给出链表中的重复元素&#xff08;链表中元素从小到大有序&#xff09;&#xff0c;使链表中的所有元素都只出现一次 例如&#xff1a; 给出的链表为1→1→2,返回1→2. 给出的链表为1→1→2→3→3返回1→2→3. 数据范围&#xff1a;链表长度满足 0≤n≤100…

ETL:数据清洗、规范化和聚合的重要性

在当今这个数据呈爆炸式增长的时代&#xff0c;数据已成为企业最为宝贵的资产之一。然而&#xff0c;数据的海量增长也伴随着诸多问题&#xff0c;如数据来源多样、结构复杂以及质量问题等&#xff0c;这些问题严重阻碍了数据的有效处理与深度分析。在此背景下&#xff0c;ETL&…

spring boot jwt生成token

1、引入jwt依赖 <!--jwt的依赖--> <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.18.3</version> </dependency> 2、创建TokenUtils工具类 package com.pn.utils;import com.…

豪越科技:融合低空经济的消防一体化安全管控解决方案

在科技飞速发展的当下&#xff0c;2025 年低空经济正处于规模化商用的关键节点&#xff0c;其在应急救援、物流配送等多领域展现出巨大潜力。豪越科技凭借其先进的消防一体化安全管控方案&#xff0c;与低空经济深度融合&#xff0c;打造出一套更为高效、智能的消防解决方案&am…

清华大学 | DeepSeek第十版!《DeepSeek政务应用场景及解决方案》

清华大学发布的《DeepSeek政务应用场景及解决方案》研究报告&#xff0c;聚焦人工智能技术DeepSeek在政府治理与公共服务中的创新实践&#xff0c;系统阐述了其如何通过智能化技术赋能政务数字化转型&#xff0c;推动治理能力现代化。报告指出&#xff0c;DeepSeek作为融合大数…

R语言双Y轴折线图+相关性注释

目录 包和数据 作图代码及详解 包和数据 rm(list ls()) library(ggpubr) library(scales) library(ggplot2)data <- iris##鸢尾花数据集 data1 <- data[1:30,c(1,2,3)] > head(data1)Sepal.Length Sepal.Width Petal.Length 1 5.1 3.5 …

2024年3月全国计算机等级考试真题(二级C语言)

&#x1f600; 第1题 下列叙述中正确的是 A. 矩阵是非线性结构 B. 数组是长度固定的线性表 C. 对线性表只能作插入与删除运算 D. 线性表中各元素的数据类型可以不同 题目解析&#xff1a; A. 矩阵是非线性结构 错误。矩阵通常是二维数组&#xff0c;属…

基于Ebay拍卖网站成交价格的影响因素分析

摘要:近些年来网上拍卖的不断地发展&#xff0c;网上购物慢慢变成了大家普遍接受的购物方式。因此关于网上拍卖的研究日益成为很多人研究的重点。 影响拍卖网站价格的因素很多&#xff0c;但很少有人分得清楚哪些因素才是比较重要的因素&#xff0c;因此对价格因素分析&#x…

Langchain中的表格解析:RAG 和表格的爱恨情仇

实现 RAG(Retrieval-Augmented Generation)是一个挑战,尤其是在有效解析和理解非结构化文档中的表格时。这在处理扫描文档或图像格式的文档时尤为困难。这些挑战至少包括以下三个方面: 1.表格的“叛逆期”:不准确的解析可能会破坏表格结构: 表格在文档里就像个叛逆的青少…

Solr-搜索引擎-入门到精通

以下是对 Apache Solr 的简介及其常用语法的快速入门指南&#xff1a; 一、Solr 是什么&#xff1f; • 核心定位&#xff1a;Apache Solr 是一个基于 Lucene 的高性能、开源的搜索平台&#xff0c;支持全文检索、分词、高亮、聚合统计等功能。 • 核心功能&#xff1a; • 全…

原生后台GPS位置限制,降低功耗

1.后台 GPS 位置限制的背景 为了控制功耗&#xff0c;Android 平台对后台应用获取位置信息的频率进行了限制。后台的定义与后台执行限制一致&#xff0c;即应用不在前台运行时被视为后台应用。 2.更新间隔限制&#xff1a; 后台应用获取位置信息的更新间隔不能超过一定阈值。…

Docker 搭建 PlantUML 服务:高效生成 UML 图的最佳实践

PlantUML 是一款开源的 UML 图形生成工具&#xff0c;它支持生成类图、时序图、用例图、活动图等多种类型的 UML 图&#xff0c;广泛应用于软件设计、文档编写以及团队沟通中。通过 Docker 安装 PlantUML&#xff0c;开发者可以快速搭建环境&#xff0c;轻松生成 UML 图&#x…

简鹿办公汇总快速打开 Windows 资源管理器的几种方式

无论你是刚开始使用电脑的新手&#xff0c;还是已经有一定经验的用户&#xff0c;了解如何在 Windows 系统中打开资源管理器都是一个非常基本且重要的技能。Windows 资源管理器&#xff08;现在称为“文件资源管理器”&#xff09;是帮助你浏览、查找和管理计算机上所有文件的主…

DNA-PAINT

参考: 【科研教程】NUPACK网页版使用教程 https://www.bilibili.com/video/BV1G94y1W7mN/NUPACK新版网页版教程-模拟部分 https://zhuanlan.zhihu.com/p/678730568NUPACK 4.0 User Guide https://docs.nupack.org/NUPACK网页版使用指南 https://zhuanlan.zhihu.com/p/55024017…

小程序内表格合并功能实现—行合并

功能介绍&#xff1a;支付宝小程序手写表格实现行内合并&#xff0c;依据动态数据自动计算每次需求合并的值&#xff0c;本次记录行内合并&#xff0c;如果列内合并&#xff0c;同理即可实现 前端技术&#xff1a;grid布局 display&#xff1a;grid 先看实现效果: axml&…