Netty知识储备:BIO、NIO、Reactor模型

学习Netty之前,首先先掌握这些基础知识:阻塞(Block)与非阻塞(Non-Block),同步(Synchronous)与异步(Asynchronous),Java BIO与NIO对比。

基础概念

阻塞(Block)与非阻塞(Non-Block)

阻塞模式

  • 调用I/O操作时,若数据未就绪,调用线程会被操作系统挂起(进入睡眠状态)
  • 线程会一直等待,直到内核缓冲区数据就绪后被唤醒
  • 典型例子:read()/write()默认的套接字操作

非阻塞模式

  • 调用I/O操作时,无论数据是否就绪都会立即返回
  • 需要通过轮询(如select/epoll)或回调机制主动检查状态
  • 典型例子:设置O_NONBLOCK标志的套接字

同步(Synchronous)与异步(Asynchronous)

同步

  • 应用程序‌主动参与‌ I/O 操作的执行过程,必须等待操作完成才能继续执行后续代码
  • 调用 I/O 函数(如 read()/write()/传统阻塞式 Socket默认模式))时,线程会阻塞直到操作完成。

注意‌:同步 ≠ 阻塞(例如非阻塞轮询也是同步行为)

异步

  • 应用程序‌发起 I/O 请求后立即返回‌,操作系统负责完成实际操作
  • 等待通知:通过回调(Callback)、事件通知(如 epoll)、信号(Signal)或 Future/Promise 机制获取结果

关键对比总结

特性同步异步
控制流应用程序主动等待结果操作系统完成后通知应用程序
线程阻塞可能阻塞(取决于实现)绝不阻塞调用线程
实现机制阻塞调用/轮询回调/事件循环/信号
性能影响可能造成线程闲置更高吞吐量

Java BIO与NIO

BIO(同步阻塞IO)

  • ‌核心类库‌

    • ServerSocket:监听TCP连接,阻塞式接受请求‌
    • Socket:客户端通信通道,读写操作均阻塞‌
    • BufferedReader/BufferedWriter:带缓冲的字符流,减少IO次数‌
  • 基础特性

    • 基于java.io包的流模型,采用‌同步阻塞‌方式操作数据流(如InputStream/OutputStream)‌
    • 线程在读写操作时会‌完全阻塞‌,直到数据就绪,导致资源闲置‌
  • 典型问题

    • 单线程阻塞‌:处理大文件或网络延迟时,线程被长时间占用‌
    • 扩展性差‌:高并发需为每个连接创建线程,易引发线程爆炸‌
  • 适用场景

    • 低并发、简单IO操作(如本地文件读写)‌

NIO(同步非阻塞IO)

  • 核心组件

    • Channel‌:双向通信管道(如SocketChannel),支持非阻塞模式‌
    • Buffer‌:数据容器(如ByteBuffer),所有读写操作通过缓冲区完成‌
    • Selector‌:多路复用器,单线程可监听多个通道事件(如读/写就绪)‌
  • 性能优势

    • 非阻塞‌:线程可轮询多个通道,避免无效等待‌
    • 高并发‌:单线程管理多个连接,减少线程切换开销‌
  • 适用场景

    • 高负载网络应用(如Web服务器、即时通讯)

BIO的通信模型

ServerSocket和Socket是如何工作的(通信流程)

BIO单线程通信模型
  • ServerSocket在服务器端绑定端口持续监听,等待客户端通信。
  • 当客户端Socket通过IP+端口发起连接请求。
  • ServerSocket触发accept()后生成专用的socket。
  • 服务端和客户端通过socket的I/o流进行双向通信。

Acceptor线程模型(多线程BIO)
 ‌核心组件分工
  • Acceptor线程
    独立运行于while(true)循环中,通过ServerSocket.accept()阻塞监听连接请求。一旦接收到新连接,生成对应的Socket对象并将其封装为任务提交至‌Worker线程池‌‌12。

  • Worker线程池
    由固定数量的线程组成,负责从任务队列中获取Socket任务,执行同步阻塞式的I/O读写(如InputStream.read()/OutputStream.write())。线程池通过复用线程避免频繁创建销毁的开销‌34。


底层执行流程
  • 初始化阶段

    • 启动ServerSocket绑定端口,创建独立的Acceptor线程和Worker线程池‌。
    • Acceptor线程进入监听状态,Worker线程池处于待命状态‌。
  • 连接处理阶段

    • 步骤1‌:客户端发起连接请求,Acceptor线程的accept()返回新Socket‌。
    • 步骤2‌:Acceptor将Socket包装为Runnable任务(如SocketHandler),提交至线程池的任务队列‌。
    • 步骤3‌:Worker线程从队列中获取任务,处理该连接的I/O操作(读写数据),期间线程被阻塞直至操作完成‌。
  • 资源释放阶段

    • I/O操作完成后,Worker线程关闭Socket并返回线程池,等待下一个任务‌。
    • 若客户端断开连接,线程会主动释放相关资源‌

对比
特性单线程模型Acceptor线程模型
线程数量1个线程处理所有连接1个Acceptor线程 + N个Worker工作线程‌
阻塞点accept()和读写均阻塞仅工作线程的读写阻塞‌
适用场景单客户端测试低并发生产环境‌
连接监听主线程直接阻塞在accept()独立Acceptor线程专责监听‌
I/O处理同一线程串行处理所有连接I/OWorker线程池并行处理‌
资源消耗线程少但完全阻塞线程池复用,可控但仍有阻塞‌
连接建立与处理串行执行,新连接需等待旧连接处理完毕并行处理,连接建立与业务解耦
崩溃影响范围线程崩溃导致整个服务不可用各阶段隔离,局部崩溃不影响其他功能

Acceptor线程模型其实可以分为两个阶段

  • 第一阶段(Acceptor线程)

    • 专注连接建立‌:通过while(true)循环持续调用ServerSocket.accept()来监听连接请求。
    • 高优先级‌:确保连接入口的高吞吐量,避免业务逻辑阻塞连接接收。
    • 崩溃隔离‌:如果Acceptor线程崩溃(如端口被占用),‌不会影响已建立的Socket连接‌(Worker线程仍在运行)。
  • 第二阶段(Worker线程池)

    • 专注业务处理‌:处理Socket的I/O操作(如HTTP请求解析、数据库查询等)。
    • 崩溃隔离‌:若某个Worker线程崩溃(如业务逻辑异常),‌不会影响Acceptor线程和其他Worker线程‌,线程池会回收异常线程并新建替补线程(取决于线程池配置)。

Acceptor线程模型升级版

若Worker线程池满载或处理缓慢,Acceptor线程仍持续提交新连接任务,可能导致线程池队列溢出或拒绝连接‌。可以采用Acceptor+线程池 或者NIO(Reactor模型

Acceptor+线程池
  • Acceptor线程‌:通过while(true)循环监听连接,接收后立即将Socket交给线程池处理‌。
  • Worker线程池‌:使用ThreadPoolExecutor处理业务逻辑,需配置核心参数(核心线程数、队列类型、拒绝策略等)‌

PS:ServerSocket.accept() 为什么会出现阻塞?

  • TCP三次握手等待
    当客户端发起连接时,需完成SYN→SYN-ACK→ACK的握手过程。若握手未完成,内核无法将连接放入"已完成连接队列",导致accept()持续等待‌。

  • 内核队列状态依赖
    accept()实际是从内核维护的ESTABLISHED状态队列中提取连接。若队列为空(无已完成握手的连接),调用线程会被挂起‌35。

  • 同步设计特性
    作为阻塞式I/O的标准行为,该设计避免了线程轮询的CPU浪费,但会牺牲响应性‌

NIO的通信模型

------------------------------------

NIO的工作过程

当Channel注册到Selector上并声明监听类型后,Selector会持续监控所有已注册的Channel。 selector会监控Channel的I/O就绪状态,如果为就绪了将会放到就绪集合。之后获取就绪集合对其进行后续的事件处理。

IO多路复用

举例说明:柜员(线程)‌快速巡视‌各个窗口(Channel)
只有亮起提示灯的窗口(就绪事件)才需要处理
处理完一个窗口立即检查下一个,‌不等待客户缓慢填单‌(非阻塞操作)

总结:多路复用其实就是“一对多”,只要就绪了就对其进行处理。传统的IO模型其实是“一对一”

select底层实现

select实现多路复用的核心分为三个阶段:准备监控、轮询扫描、事件处理,整个过程围绕fd_set位图机制展开。‌

  • 准备阶段

    • 用户通过FD_SET宏将待监控的文件描述符(fd)加入fd_set位图
    • 提前标记需要关注的fd(如网络socket)
  • 轮询阶段

    • 内核通过系统调用全量扫描位图中的所有fd
    • 通过位图状态位判断哪些fd已就绪(如可读/可写)
    • 相当于"服务员检查所有餐桌"的阻塞过程
  • 处理阶段

    • 用户遍历内核返回的就绪事件集合
    • 对每个就绪fd执行对应IO操作

关于 select() 的数据拷贝时机,其核心流程中的拷贝操作发生在两个关键阶段:

  1. 调用 select() 时
    用户态程序会将监控的 fd_set 位图(包含所有待监控的 fd)‌完整拷贝到内核态‌,这是全量扫描的前提。此时内核需要获取完整的 fd 集合信息才能开始遍历检查。

  2. 返回结果时
    内核完成全量扫描后,会将‌就绪的 fd 标记‌在新的 fd_set 位图中,并将该结果位图‌拷贝回用户态‌。用户程序需通过 FD_ISSET 遍历位图解析就绪事件

select()底层原理总结:

select() 其实主要通过fd_set位图进行对fd(文件描述符)进行监控,系统触发全量fd扫描,根据fd的状态监测就绪事件,最后对就绪事件进行处理。

epoll底层实现

epoll的工作流程可分为三个核心阶段,结合红黑树和就绪队列实现高效事件管理:

  • 初始化阶段

    • 创建epoll实例(epoll_create),内核会初始化红黑树和就绪链表结构
    • 红黑树用于存储所有待监控的fd(文件描述符),确保快速插入/删除
  • 事件注册阶段

    • 通过epoll_ctl将fd添加到红黑树,并设置回调函数(如读/写事件)
    • 网卡驱动通过中断触发回调,将活跃事件对应的节点移至就绪队列
  • 事件轮询阶段

    • epoll_wait系统调用直接获取就绪队列中的事件,无需全量扫描
    • 用户空间仅处理实际活跃的连接,时间复杂度O(1)
  • 关键优化点

    • 零拷贝‌:用户态与内核态通过共享内存传递就绪事件(
      典型实现如sendfile系统调用,直接将文件数据从磁盘经内核缓冲区传输到网卡缓冲区 )
    • 边缘触发(ET)‌:减少重复事件通知,需配合非阻塞I/O使用
    • LT/ET模式‌:LT(水平触发)会重复通知未处理事件,ET(边缘触发)仅通知一次

总结:

epoll通过‌红黑树‌和‌就绪队列‌两级数据结构实现高效事件管理:

  1. 红黑树‌作为全局存储,维护所有待监控的文件描述符(fd)
  2. 事件驱动机制‌通过回调函数(如网卡中断触发)将活跃事件对应的fd节点移至‌就绪队列‌;
  3. 最终epoll_wait仅需扫描就绪队列中的活跃事件,避免全量fd集合的遍历扫

epoll与select/poll的关键架构差异。具体表现为:

  1. epoll的就绪队列机制

    • 内核通过红黑树管理监控fd集合,同时‌独立维护双向链表结构的就绪队列
    • 网卡中断触发回调时,内核直接将活跃事件对应的epitem节点插入队列,无需遍历检查
    • epoll_wait仅需读取该队列内容,时间复杂度恒为O(1)
  2. select/poll的临时检测机制

    • 每次调用时需‌全量扫描监控的fd集合‌,通过轮询检查每个fd状态
    • 返回的"就绪列表"是临时生成的位图(poll是revents数组),非持续维护结构
    • 即使仅1个fd就绪,仍需完成O(n)次扫描

单线程的 Reactor 模型

工作流程
  • 事件监听‌:Reactor线程通过select/epoll轮询监听所有连接事件
  • 事件分发‌:
    • 连接事件 → 交给Acceptor处理(创建新连接并注册Handler)
    • 读写事件 → 分发给对应Handler处理
  • 业务处理‌:Handler完成数据读取→业务计算→响应发送的全流程
典型应用场景
  • Redis的多路复用模型采用此模式
  • 适合低并发、轻量级业务场景

总结:reactor主要是负责监听和事件分发(Dispatcher分发事件),监听通过多路复用器(底层使用select和epoll),而事件分发如果是 连接事件交给Acceptor处理(创建新连接并注册Handler),读写事件的话直接交给handler处理。

事件分类 
  • ACCEPT事件‌:

    1. 接受客户端连接
    2. 创建对应的SocketChannel
    3. 注册READ事件到Selector
  • READ事件‌:

    1. 从Channel读取数据到Buffer
    2. 解码并处理业务逻辑
    3. 如有响应,注册WRITE事件
  • WRITE事件‌:

    1. 将响应数据写入Buffer
    2. 从Buffer写入Channel
    3. 完成后取消WRITE事件注册

PS:

事件处理流程‌:

  • 连接事件 → Reactor → Acceptor
    • 创建SocketChannel
    • 注册READ事件到Selector
    • 绑定对应Handler
  • 读写事件 → Reactor → Handler
    • 读:Channel→Buffer→业务处理
    • 写:业务数据→Buffer→Channel
思考:
为什么连接事件交给Acceptor处理?

Acceptor专职处理连接事件(ACCEPT),因其涉及底层系统调用(如bind/listen)和资源初始化,需与业务逻辑隔离;

为什么读写事件直接交给Handler处理?

读写事件直接由Handler处理,避免冗余中转,实现数据到业务的最短路径。这种分工既保障了连接稳定性,又提升了数据处理效率

selector中的SelectionKey‌是什么东西,它作用是什么?

SelectionKey就是NIO中事件的通知单——它标记了哪个Channel触发了什么事件(比如可读/可写),并携带对应的上下文数据,相当于Selector和Channel之间的"事件快递员"

Handler的创建与绑定机制

Handler的创建和绑定主要通过以下方式确保:

  • 创建时机‌:

    • 在Acceptor接受新连接时创建(最常见)
    • 预创建线程池中的Handler实例(多线程模型)
    • 延迟初始化(按需创建)
  • 绑定方式‌:

    • 通过SelectionKey(attachment)关联
对应的SelectionKey无有效attachment怎么处理

若SelectionKey.attachment()返回null或无效对象,多数实现会直接关闭该Channel并取消Key注册,避免资源泄漏;
读事件特殊性的处理‌,即使无Handler,底层仍会触发读就绪通知,但数据会被丢弃(通过执行channel.read(ByteBuffer)清空缓冲区)

最佳实践建议

  • 在Acceptor阶段必须显式绑定Handler到新Channel
  • 通过key.isValid()+attachment()!=null双重校验防御无效事件
  • 对异常Channel实现fallback处理策略(如重连机制)

事件触发 → 检查Key.attachment() → 存在Handler → 调用对应方法
不存在 → 关闭Channel或创建应急Handler

典型问题处理
  • 事件堆积
    需及时处理就绪事件并调用selectedKeys().clear(),否则会导致重复触发。

  • 内存泄漏
    长时间未关闭的Channel会导致SelectionKey堆积,需通过key.cancel()主动释放。

  • 并发冲突
    多线程修改interestOps()需同步(如使用selector.wakeup()

多线程的 Reactor 模型

核心组件与职责

  • Reactor(反应器)

    • 职责‌:统一监听所有I/O事件(连接、读写),通过I/O多路复用(如epoll)实现非阻塞监听。
    • 线程模型‌:由多个线程共同运行事件循环(EventLoop),每个线程独立处理一组Channel
  • ‌Handler(处理器)

    • 职责‌:执行数据读写和业务逻辑,通常与Reactor线程绑定,避免跨线程竞争。
    • 优化点‌:若业务耗时较长,可提交至独立Worker线程池处理。
  • Worker线程池(可选)

    • 职责‌:异步处理耗时业务逻辑(如数据库操作),与Reactor线程解耦

执行过程

  • Reactor 通过监听客户端请求事件。
  • 如果是连接事件,Acceptor 通过 accept 接受连接,并注册到 Reactor 中,之后创建一个 Handler 处理后续事件。
  • 如果是读写事件,Reactor 调用对应的 Handler 处理。
  • Handler 只负责读取数据,将业务处理交给 Worker 线程池。
  • Worker 线程池 完成业务处理,将结果返回给 Handler,由 Handler 发送给客户端。

当客户端发起连接时,EventLoop会通过Selector检测到ACCEPT事件,立即调用Acceptor接收新连接,并将生成Channel的注册到自己的Selector上监听读事件。当Channel有数据到达触发OP_READ时,EventLoop会调用Handler读取数据,然后将需要复杂计算的业务逻辑提交给Worker线程池处理。Worker线程完成计算后,通过任务队列将结果回调给EventLoop线程,最终由EventLoop负责将结果写回客户端。整个过程就像高效的流水线,EventLoop专注I/O调度,耗时操作交给线程池,既保证了响应速度又提升了吞吐量。

非主从模型中‌:只有一个EventLoop线程负责所有事件的监听和分发

EventLoop与线程的对应关系

模型类型EventLoop数量线程数量任务处理方式
单线程Reactor1个1个所有任务串行执行
多线程Reactor1个N+1个EventLoop线程 + Worker线程池

Worker线程池的核心作用

  • 职责分离原则

    • EventLoop线程仅处理IO事件(如epoll事件监听)
    • Worker线程池专职处理‌耗时业务逻辑‌(如数据库查询、复杂计算)26
  • 性能优化关键

    • 避免阻塞EventLoop线程,保证IO事件响应速度
    • 通过线程池复用线程资源,降低线程创建销毁开销

经典问题解析

  • Q1:EventLoop如何保证线程安全?
    通过任务队列的互斥锁(如pthread_mutex_t)实现生产-消费模型,EventLoop线程与Worker线程无共享状态

  • Q2:EventLoop卡顿怎么办?
    监控任务队列积压,动态扩容Worker线程池或拆分耗时任务

  • Q3:Netty中如何实现?
    通过NioEventLoopGroup管理I/O线程组,单个NioEventLoop绑定一个Selector处理多Channel

  • Q4:如何配置Worker线程池的最佳参数
    核心参数配置策略‌得考虑是CPU密集型任务‌还是I/O密集型任务不同的任务类型需要不同的配置,同时还得考虑拒绝策略选择。

  • Q5:Selector是如何检测ACCEPT事件的?
    epoll机制或者select机制

主从多线程的 Reactor 模型

主从模型中主Reactor和子Reactor如何协作

主从Reactor模型的协作机制通过分层分工实现高效事件处理,具体流程如下:


1. ‌主Reactor职责
  • 连接监听‌:主Reactor(Main-Reactor)由独立线程运行,通过Acceptor监听服务端端口,专门处理新连接请求。
  • 连接分配‌:当新连接到达时,主Reactor调用accept()创建SocketChannel,并通过轮询或负载均衡策略将其动态注册到某个子Reactor的Selector上。
  • 非阻塞设计‌:主Reactor仅处理连接事件,不参与I/O操作,避免阻塞后续连接请求。
2. ‌子Reactor职责
  • 事件监听‌:每个子Reactor(Sub-Reactor)运行在独立线程中,通过多路复用器(如epoll)监听已注册Channel的读写事件。
  • 任务分发‌:当检测到I/O事件时,子Reactor将任务(如读/写操作)封装为回调函数,压入任务队列异步处理。
  • 优先级处理‌:优先处理简单I/O事件,耗时任务(如业务逻辑)交由线程池(Worker)执行,避免阻塞事件循环。
3. ‌协作流程示例
  1. 连接阶段‌:客户端请求到达 → 主Reactor的Acceptor接收连接 → 分配至子Reactor。
  2. I/O阶段‌:子Reactor监听连接事件 → 触发Handler读取数据 → 线程池处理业务逻辑 → Handler回写结果。
  3. 资源隔离‌:主/子Reactor线程互不干扰,子Reactor间通过任务队列实现负载均衡

谈谈你对Reactor模型的理解

Reactor模型本质上是一种高效的事件驱动架构,它通过I/O多路复用技术(如select/epoll)实现单线程监听大量网络连接,将就绪事件分发给对应的处理器执行。这种模型的核心价值在于解决了传统阻塞IO中"一连接一线程"的资源浪费问题,通过主从Reactor的分层设计——主线程专注接收新连接,子线程组处理已建立连接的I/O事件,再结合业务线程池异步执行耗时操作,形成连接处理、I/O操作与业务逻辑的三级流水线。在实际工程中(如Netty框架),这种设计既能保证高并发场景下的吞吐量,又通过Channel与EventLoop的绑定机制维持线程安全,使得系统在应对百万级连接时仍能保持优雅的扩展性。

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

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

相关文章

用生成器守住架构,用 AI 放大效率:一套可落地的 AI 编程方法论

背景与问题 现实困境: 直接让 AI 产出整块业务代码,常常与现有架构风格、分层边界、依赖策略不一致,后续改造成本高;AI 对现实业务语境、领域规则难以精准把握;在既定模板成熟的场景下,代码生成器往往更快、更整齐。目…

码头岸电系统如何保障供电安全?安科瑞绝缘监测及故障定位方案解析

当岸电电网是TN-S系统时,船体未接专用接地线且船舶电网未与岸电零线接通,船舶电网发生单相接地故障时,人站在岸上触及船体会有触电危险,零线上可能出现高电压,单相接地电流大。当船体接专用接地线且船舶电网接入岸电零…

ESP32_u8g2移植

前言 U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306 SSD1315等多种类型的OLED驱动,几乎市面上常见都支持。 U8g2源码 download:https://github.com/olikraus/u8g21:环境 ESP32 S3(ESP32-S3-Dev…

MCP实现:.Net实现MCP服务端 + Ollama ,MCP服务端工具调用

本文使用.Net编写MCP服务端 Ollama ,实现简单MCP调用,代码仅实现基本演示功能。 文章目录一、Ollama如何安装使用二、创建.Net8项目,开发MCP服务端三、开发MCP客户端,并对接Ollama一、Ollama如何安装使用 请移步:htt…

Docker的安装使用以及常见的网络问题

一、什么是DockerDocker是一种容器化技术,用于快速打包、分发和运行程序。他的核心思想是"一次构建,到处运行",通过将应用及其依赖的环境打包到一个轻量级、可移植的容器中,实现跨平台一致运行。二、Docker的安装1.Cent…

C++入门学习

1.命名空间的介绍首先我们看到如下的代码&#xff0c;在C语言中&#xff1a;#include <stdio.h> #include <stdlib.h> int rand 10; // C语言没办法解决类似这样的命名冲突问题&#xff0c;所以C提出了namespace来解决 int main() {printf("%d\n", rand…

解决python错误:playwright._impl._errors.TimeoutError: Timeout 30000ms exceeded.

from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page() page.goto(url)page.wait_for_load_state(networkidle) 在Python环境中运行以上代码后报错: page.wait_for_load_…

爬虫逆向之雷池waf

本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的。否则由此产生的一切后果均与作者无关&#xff01; 雷池waf概念 雷池 WAF&#xff08;SafeLine&#xff09;是长亭科技开源的一款 Web 应用防火墙&#xff0c;部署在网站前面&#xff0c;把所有进来的 HTTP/…

23种设计模式解析--行为型

行为型模式&#xff08;协作的艺术&#xff09; 观察者模式 观察者模式详解 模式定义 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;用于建立对象间一对多的依赖关系。当一个对象&#xff08;Subject&#xff09;状态变化时&#xff0c;所…

Linux系统之lua 详解

命令简介 lua 是 Lua 语言的解释器&#xff0c;用于加载和执行 Lua 程序&#xff08;包括文本源码和预编译的二进制文件&#xff09;。它支持两种运行模式&#xff1a;批处理模式&#xff08;执行指定脚本文件&#xff09;和交互式模式&#xff08;逐行读取并执行输入的命令&am…

visual studio 无明显错误,但是无法编译成功解决—仙盟创梦IDE

往后面查看rror CS0246: 未能找到类型或命名空间名“SimpleClass”(是否缺少 using 指令或程序集引用?)修复阿雪技术观在科技发展浪潮中&#xff0c;我们不妨积极投身技术共享。不满足于做受益者&#xff0c;更要主动担当贡献者。无论是分享代码、撰写技术博客&#xff0c;还是…

《论文阅读》传统CoT方法和提出的CoT Prompting的区分

论文&#xff1a;Chain-of-Thought Prompting Elicits Reasoning in Large Language Models作者对传统CoT方法和本文提出的CoT Prompting的区分。1. 传统方法的局限性 (1) 基于微调的CoT&#xff08;Rationale-Augmented Training&#xff09; 实现方式&#xff1a;需人工标注大…

Minio 高性能分布式对象存储

1、什么是对象存储? 描述: 对象存储&#xff08;Object Storage&#xff09;是一种存储数据的计算机体系结构&#xff0c;它以对象的形式存储和管理数据。与传统的文件系统和块存储不同&#xff0c;对象存储将数据作为对象存储在分布式的存储集群中&#xff0c;每个对象都有一…

[深度学习] 大模型学习4-RAG技术全景解析

在大语言模型基础知识一文中&#xff0c;检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称 RAG&#xff09;技术作为构建大语言模型&#xff08;Large Language Model&#xff0c;简称 LLM&#xff09;应用的一种方式已被简要提及&#xff0c;本文将详…

4G/5G无线电单元系统

4G/5G无线电单元系统 ADI公司的核心技术和领域专业知识帮助客户在全球范围内规划、设计、打造更出色的高性能通信系统。 我们的无线电单元(RU)设计平台利用新一代技术来提供高性能解决方案&#xff0c;帮助客户消除设计障碍、缩短产品开发周期&#xff0c;加快产品上市时间。 价…

HarvardX TinyML小笔记1(番外2:神经网络)

1 介绍 图片来自&#xff1a;https://zh.wikipedia.org/zh-cn/%E4%BA%BA%E5%B7%A5%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C 神经网络一直感觉挺神奇的&#xff0c;江湖也说可解释性很差&#xff0c;无论如何还是学学吧。借这次学习哈佛的TinyML&#xff0c;也就顺带弄了。 这里…

计算机网络 第2章通信基础(竟成)

第 2 章 物理层【考纲内容】1.通信基础 (1) 信道、信号、带宽、码元、波特、速率、信源与信宿等基本概念 (2) 奈奎斯特定理与香农定理 (3) 编码与调制 (4) 电路交换、报文交换与分组交换 (5) 数据报与虚电路2.传输介质 (1) 双绞线、同轴电缆、光纤与无线传输介质&#xff1b;(2…

2025-08-09通过授权码的方式给exe程序充值

2025-08-09通过授权码的方式给exe程序充值主要点&#xff1a; 一次性授权机制&#xff1a; 新增 .used_licenses 文件记录所有已使用的授权码 每次激活前检查授权码是否在已使用列表中 激活成功后立即将授权码标记为已使用 时效性验证&#xff1a; 授权码包含过期时间戳&#x…

工具类-高效集合差异计算工具DiffWrapper

集合差异工具类-DiffWrapper 原因 在编辑过程中&#xff0c;肯定会存在对于子表的更新操作&#xff0c;这种更新分为三种&#xff1a; 要加的&#xff0c; 要删的&#xff0c;要更新的&#xff0c;并且传参只有一个modifyVO的, 每一个都写有点过于冗余&#xff0c;故考虑提取一…

SimBA算法实现过程

文章目录添加噪声衡量扰动示例数值总结高级索引变量名代码总体代码添加噪声 操作&#xff1a;将频率扰动通过trans( )转为像素域扰动加到原始图像上&#xff08;trans返回频率域转换为像素域的结果&#xff09; expanded (images_batch[remaining_indices] # 原始图像&…