04-netty基礎-Reactor三種模型

1 基本概念

Reactor模型是一種事件驅動(Event-Driven)的設計模式,主要用于高效處理高并發、I/O密集型場景(如網絡、服務器、分布式等)。其核心思想就是集中管理事件,將I/O操作與業務邏輯解耦,避免傳統多線程模型中線程切換的開銷,從而提升系統的吞吐量和響應速度。

核心目標:
在高并發場景下,傳統的 “一連接一線程” 模型會因線程創建 / 銷毀、上下文切換的開銷過大而效率低下。Reactor 模型通過以下方式解決這一問題:

  • 單個或少量線程監聽多個 I/O 事件(如網絡連接、數據讀寫),避免線程資源浪費;
  • 僅當事件觸發(如客戶端發送數據)時才執行對應處理邏輯,實現 “事件就緒才處理” 的高效調度。

2 核心組件

?Reactor 模型的運行依賴四個關鍵組件,它們協同完成事件的檢測、分發與處理:
1、事件源
產生事件的源頭,通常是I/O相關的資源,例如:
網絡套接字(Socket):客戶端連接、數據發送/接收等事件的源頭? ? ? ??
文件描述符(FD):文件讀寫、異常等事件的源頭
2、事件多路分發器(Event Demultiplexer)
又稱 “I/O 多路復用器”,是 Reactor 模型的 “感知器官”。
作用:持續監聽多個事件源的事件(如 “可讀”“可寫”“異常”),當事件觸發時標記為 “就緒”;
底層依賴:操作系統提供的 I/O 多路復用系統調用,如 Unix/Linux 的select/poll/epoll,或 BSD 的kqueue。

3、反應器(Reactor)
模型的 “核心調度者”,是事件處理的中樞。
作用:從事件多路分發器獲取 “就緒事件”,根據事件類型和關聯的事件源,分發給對應的事件處理器;
本質:通過 “事件注冊 - 事件監聽 - 事件分發” 的邏輯,實現對所有事件的集中管理。

4 事件處理器(Handler)
負責具體業務邏輯的 “執行者”。
作用:定義事件處理的回調方法(如handleRead處理可讀事件、handleWrite處理可寫事件),由 Reactor 觸發執行;
特點:僅關注業務邏輯(如解析請求、生成響應),不關心事件的檢測與分發。

3 單Reactor單線程模型

3.1 概念

? ? ? ? 在單Reactor單線程模型中,他們的作用以及實現邏輯,首先客戶端訪問服務端,在服務端這邊首先是使用Reactor監聽accept事件和read事件,當有連接過來,就交給acceptor處理accept事件,當觸發read事件,同時accept或把read事件交給handler處理。所有動作都是由一個線程完成的。

特點:單線程Reactor模型編程簡單,比較適用于每個請求都可以快速完成的場景,但是不能發揮出多核CPU的優勢,在一般情況下,不會使用單Reactor單線程模型。

3.2 原理圖

3.3 代碼實現

3.3.1 入口

入口: 啟動Reactor線程

package com.bonnie.netty.reactor.single;import java.io.IOException;/*** 單Reactor單線程模型*/
public class Main {public static void main(String[] args) throws IOException {new Thread(new Reactor(8080, "Main-Thread")).start();}}

3.3.2 Reactor

1、啟動服務端ServerSocketChannel
2、監聽accept事件
3、監聽read事件

package com.bonnie.netty.reactor.single;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;/*** 模擬Reactor的單線程模型*/
public class Reactor implements Runnable {Selector selector;ServerSocketChannel serverSocketChannel;public Reactor(int port, String threadName) throws IOException {selector = Selector.open();serverSocketChannel = ServerSocketChannel.open();// 綁定端口serverSocketChannel.bind(new InetSocketAddress(port));// 設置成非阻塞serverSocketChannel.configureBlocking(Boolean.FALSE);// 注冊OP_ACCEPT,事件,會調用Acceptor.run方法serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, new Acceptor(selector, serverSocketChannel));}@Overridepublic void run() {while (!Thread.interrupted()) {try {// 阻塞selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {// 我們之前說的分發事件就是這個地方分發了, 此處可能是accept事件,也可能是read事件dispatcher(iterator.next());// 分發完之后要刪除key,防止重復keyiterator.remove();}} catch (IOException e) {throw new RuntimeException(e);}}}private void dispatcher(SelectionKey key) {// 然后在這里通過key獲取這個attachment,執行他的run方法,記住,這里并沒有開啟線程,所有叫做單線程Reactor單線程模型Runnable runnable = (Runnable)key.attachment();if (runnable!=null) {runnable.run();}}}

?3.3.3?Acceptor

1、處理accept請求
2、把read事件轉發給handler處理

package com.bonnie.netty.reactor.single;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;/*** 接收連接請求,并注冊handle到selector*/
public class Acceptor implements Runnable{Selector selector;ServerSocketChannel serverSocketChannel;public Acceptor(Selector selector, ServerSocketChannel serverSocketChannel) {this.selector = selector;this.serverSocketChannel = serverSocketChannel;}@Overridepublic void run() {try {SocketChannel socketChannel = serverSocketChannel.accept();System.out.println(socketChannel.getRemoteAddress() + " 收到連接!!!");// 設置成非阻塞socketChannel.configureBlocking(Boolean.FALSE);// 注冊事件,交由Handler處理socketChannel.register(selector, SelectionKey.OP_READ, new Handler(socketChannel));} catch (IOException e) {throw new RuntimeException(e);}}}

?3.3.4?Handler

處理read事件

package com.bonnie.netty.reactor.single;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;/*** 接收連接請求,并注冊handle到selector*/
public class Acceptor implements Runnable{Selector selector;ServerSocketChannel serverSocketChannel;public Acceptor(Selector selector, ServerSocketChannel serverSocketChannel) {this.selector = selector;this.serverSocketChannel = serverSocketChannel;}@Overridepublic void run() {try {SocketChannel socketChannel = serverSocketChannel.accept();System.out.println(socketChannel.getRemoteAddress() + " 收到連接!!!");// 設置成非阻塞socketChannel.configureBlocking(Boolean.FALSE);// 注冊事件,交由Handler處理socketChannel.register(selector, SelectionKey.OP_READ, new Handler(socketChannel));} catch (IOException e) {throw new RuntimeException(e);}}}

3.3.5 碼云位置

git地址:?https://gitee.com/huyanqiu6666/netty.git? ? 分支:?250724-reactor

4 單Reactor多線程模型

4.1 概念

解決單Reactor單線程模型的不足,使用多線程處理handler提升處理能力,增加吞吐量。

4.2 原理圖

4.3 代碼實現

4.3.1 入口

package com.bonnie.netty.reactor.mult;import java.io.IOException;/*** 單reactor多線程模型:處理handle的時候是線程池*/
public class MultMain {public static void main(String[] args) throws IOException {new Thread(new MultReactor(8080, "Main-Thread")).start();}}

4.3.2 MultReactor

package com.bonnie.netty.reactor.mult;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;/*** 模擬單Reactor多線程模型* 1、監聽accept事件* 2、監聽read事件*/
public class MultReactor implements Runnable {Selector selector;ServerSocketChannel serverSocketChannel;public MultReactor(int port, String threadName) throws IOException {selector = Selector.open();serverSocketChannel = ServerSocketChannel.open();// 綁定端口serverSocketChannel.bind(new InetSocketAddress(port));// 設置成非阻塞serverSocketChannel.configureBlocking(Boolean.FALSE);// 注冊OP_ACCEPT,事件,會調用Acceptor.run方法serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, new MultAcceptor(selector, serverSocketChannel));}@Overridepublic void run() {while (!Thread.interrupted()) {try {// 阻塞selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {// 我們之前說的分發事件就是這個地方分發了, 此處可能是accept事件,也可能是read事件dispatcher(iterator.next());// 分發完之后要刪除key,防止重復keyiterator.remove();}} catch (IOException e) {throw new RuntimeException(e);}}}private void dispatcher(SelectionKey key) {// 然后在這里通過key獲取這個attachment,執行他的run方法,記住,這里并沒有開啟線程,所有叫做單線程Reactor單線程模型Runnable runnable = (Runnable)key.attachment();if (runnable!=null) {runnable.run();}}}

4.3.3 MultAcceptor

package com.bonnie.netty.reactor.mult;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;/*** 接收連接請求,并注冊handle到selector* 1、處理accept事件* 2、read事件轉發給handler*/
public class MultAcceptor implements Runnable{Selector selector;ServerSocketChannel serverSocketChannel;public MultAcceptor(Selector selector, ServerSocketChannel serverSocketChannel) {this.selector = selector;this.serverSocketChannel = serverSocketChannel;}@Overridepublic void run() {try {SocketChannel socketChannel = serverSocketChannel.accept();System.out.println(socketChannel.getRemoteAddress() + " 收到連接!!!");// 設置成非阻塞socketChannel.configureBlocking(Boolean.FALSE);// 注冊事件,交由Handler處理socketChannel.register(selector, SelectionKey.OP_READ, new MultHandler(socketChannel));} catch (IOException e) {throw new RuntimeException(e);}}}

4.3.4 MultHandler

package com.bonnie.netty.reactor.mult;import org.apache.commons.lang3.StringUtils;import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;/*** Handler將read事件給線程池處理*/
public class MultHandler implements Runnable {private SocketChannel socketChannel;public MultHandler(SocketChannel socketChannel) {this.socketChannel = socketChannel;}private Executor executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);@Overridepublic void run() {// 放到線程池中處理executor.execute(new ReadHandle(socketChannel));}private class ReadHandle implements Runnable{private SocketChannel socketChannel;public ReadHandle(SocketChannel socketChannel) {this.socketChannel = socketChannel;}@Overridepublic void run() {System.out.println("線程名稱:" + Thread.currentThread().getName());// 定義一個ByteBuffer的數據結構ByteBuffer byteBuffer = ByteBuffer.allocate(1024);int len=0, total=0;String msg = StringUtils.EMPTY;try {do {len = socketChannel.read(byteBuffer);if (len > 0) {total += len;msg += new String(byteBuffer.array());}System.out.println(socketChannel.getRemoteAddress() + "客戶端的消息已收到," + msg);} while (len>byteBuffer.capacity());} catch (IOException e) {throw new RuntimeException(e);}}}}

4.3.5 碼云位置

git地址:?https://gitee.com/huyanqiu6666/netty.git? ? 分支:?250724-reactor

5 主從Reactor模型

5.1 概念

5.2 原理圖

5.3 代碼實現

5.3.1 入口

package com.bonnie.netty.reactor.main;import java.io.IOException;/*** 主從Reactor多線程模型*/
public class MainMain {public static void main(String[] args) throws IOException {new Thread(new MainReactor(8080), "Main-Thread").start();}}

5.3.2?MainReactor

package com.bonnie.netty.reactor.main;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;/*** 構建Selector、ServerSocketChannel綁定端口,設置成非阻塞* 注冊accept事件*/
public class MainReactor implements Runnable {private final Selector selector;private final ServerSocketChannel serverSocketChannel;public MainReactor(int port) throws IOException {// 主Reactor負責監聽accept事件selector = Selector.open();serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(port));serverSocketChannel.configureBlocking(Boolean.FALSE);// 添加attachment為acceptorserverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, new MainAcceptor(serverSocketChannel));}@Overridepublic void run() {while (!Thread.interrupted()) {try {// 等待客戶端的連接到來selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {// 當有連接過來的時候就會轉發任務dispatch(iterator.next());iterator.remove();}} catch (IOException e) {throw new RuntimeException(e);}}}private void dispatch(SelectionKey key) {// 可能拿到的對象有兩個  Acceptor HandlerRunnable runnable = (Runnable)key.attachment();if (runnable!=null) {runnable.run();}}
}

5.3.3?SubReactor

package com.bonnie.netty.reactor.main;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;/*** 子Reactor*/
public class SubReactor implements Runnable{private Selector selector;public SubReactor(Selector selector) {this.selector = selector;}@Overridepublic void run() {while (true) {try {// 所有的子Reactor阻塞selector.select();System.out.println("selector:"+selector.toString()+"thread:"+Thread.currentThread().getName());Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {dispacher(iterator.next());iterator.remove();}} catch (IOException e) {throw new RuntimeException(e);}}}private void dispacher(SelectionKey selectionKey) {// 此處會調用workHandler里面的方法Runnable runnable = (Runnable) selectionKey.attachment();if (runnable!=null) {runnable.run();}}
}

5.3.4?MainAcceptor

package com.bonnie.netty.reactor.main;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;/*** 處理MainAcceptor請求*/
public class MainAcceptor implements Runnable{private ServerSocketChannel serverSocketChannel;private final Integer core = Runtime.getRuntime().availableProcessors() * 2;private Integer index = 0;private Selector[] selectors = new Selector[core];private SubReactor[] subReactors = new SubReactor[core];private Thread[] threads = new Thread[core];/*** 構造方法* 1、初始化多個SubReactor* 2、初始化多個Selector* 3、每個SubReactor都有一個Selector* 4、創建線程包裝SubReactor* 5、啟動線程,也就是調用每一個SubReactor的run方法*/public MainAcceptor(ServerSocketChannel serverSocketChannel) throws IOException {this.serverSocketChannel = serverSocketChannel;for (int i=0; i<core; i++) {selectors[i] = Selector.open();subReactors[i] = new SubReactor(selectors[i]);threads[i] = new Thread(subReactors[i]);// 一初始化就工作起來threads[i].start();}}@Overridepublic void run() {try {System.out.println("acceptor thread: " + Thread.currentThread().getName());// 此處就會接收連接的socketChannelSocketChannel socketChannel = serverSocketChannel.accept();System.out.println("有客戶端上來了:"+socketChannel.getRemoteAddress());socketChannel.configureBlocking(Boolean.FALSE);// 立即喚醒第一個阻塞的selectorselectors[index].wakeup();// 然后注冊Read事件到該selectorsocketChannel.register(selectors[index], SelectionKey.OP_READ, new WorkHandler(socketChannel));index = (++index) % core;} catch (IOException e) {throw new RuntimeException(e);}}
}

5.3.5?WorkHandler

package com.bonnie.netty.reactor.main;import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;/*** SubReactor把事件交給WorkHandler去執行*/
public class WorkHandler implements Runnable{private SocketChannel socketChannel;public WorkHandler(SocketChannel socketChannel) {this.socketChannel = socketChannel;}@Overridepublic void run() {try {System.out.println("WorkHandler thread:" + Thread.currentThread().getName());ByteBuffer buffer = ByteBuffer.allocate(1024);// 數據讀取到socketChannel中socketChannel.read(buffer);String msg = new String(buffer.array(), StandardCharsets.UTF_8);System.out.println(socketChannel.getRemoteAddress() + "發來了消息:" + msg);// 給客戶端會寫消息socketChannel.read(ByteBuffer.wrap("你的消息已收到".getBytes(StandardCharsets.UTF_8)));} catch (IOException e) {throw new RuntimeException(e);}}
}

5.3.6 碼云位置

git地址:?https://gitee.com/huyanqiu6666/netty.git? ? 分支:?250724-reactor



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/90769.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/90769.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/90769.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

踩坑無數!NFS服務從入門到放棄再到真香的血淚史

前言 說起NFS&#xff0c;我估計很多搞運維的兄弟都有一肚子話要說。這玩意兒吧&#xff0c;看起來簡單&#xff0c;用起來坑多&#xff0c;但是真正搞明白了又覺得挺香的。 前幾天有個朋友問我&#xff0c;說他們公司要搭建一個文件共享系統&#xff0c;問我推薦什么方案。我…

矩陣譜分解的證明及計算示例

1. 矩陣譜分解的條件矩陣的譜分解&#xff08;也稱為特征分解&#xff09;是將一個矩陣分解為一系列由其特征向量和特征值構成的矩陣乘積的過程。進行譜分解的前提條件包括&#xff1a;<1.> 矩陣是可對角化的&#xff08;Diagonalizable&#xff09;&#xff0c;即矩陣存…

Leetcode 07 java

169. 多數元素 給定一個大小為 n 的數組 nums &#xff0c;返回其中的多數元素。 多數元素是指在數組中出現次數 大于 ? n/2 ? 的元素。 你可以假設數組是非空的&#xff0c;并且給定的數組總是存在多數元素。 示例 1&#xff1a; 輸入&#xff1a;nums [3,2,3] 輸出&a…

CS231n-2017 Lecture6訓練神經網絡(一)筆記

本節主要講的是模型訓練時的算法設計數據預處理&#xff1a;關于數據預處理&#xff0c;我們有常用的3個符號&#xff0c;數據矩陣X&#xff0c;假設其尺寸是&#xff0c;N是數據樣本的數量&#xff0c;D是數據的維度均值減法(Mean subtraction)&#xff1a;是預處理最常用的形…

C++ 中實現 `Task::WhenAll` 和 `Task::WhenAny` 的兩種方案

&#x1f4da; C 中實現 Task::WhenAll 和 Task::WhenAny 的兩種方案 引用&#xff1a; 拈朵微笑的花 想一番人世變換 到頭來輸贏又何妨日與夜互消長 富與貴難久長 今早的容顏老於昨晚C 標準庫異步編程示例&#xff08;一&#xff09;C TAP&#xff08;基于任務的異步編程…

【學習】Codeforces Global Round 15 C. Maximize the Intersections

題意&#xff1a;給出一個圓&#xff0c;順時針排布1~2*n&#xff0c;已知連了k條邊&#xff0c;問這個圓最好情況下有多少個線的交點&#xff0c;要求線與線之間不能有重復的連接點&#xff0c;也就是每個點只能被一條線連接 思路&#xff1a; 1.考慮沒有線的時候&#xff0…

圖論:Dijkstra算法

昨天介紹了最小生成樹的兩個算法&#xff0c;最小生成樹的兩個算法旨在求解無向有權圖中的最小代價聯通圖的問題&#xff0c;那么對于有向有權圖&#xff0c;從起點到終點的最小花費代價問題就可以用 Dijkstra 算法來解決而且Dijkstra算法可以求出來從起始點開始到所有節點的最…

WPFC#超市管理系統(2)顧客管理、供應商管理、用戶管理

超市管理系統3. 顧客管理3.1 顧客新增3.2 DataGrid樣式3.3 顧客刪除3.4 顧客修改4. 供應商管理4.1 供應商管理主界面4.2 新增供應商4.3 修改供應商5. 用戶管理5.1 用戶管理主界面5.2 新增用戶5.3 修改用戶總結3. 顧客管理 在CustomerView.xaml使用命令綁定方式添加頁面加載Loa…

Windows本地部署DeepSeek

1、Ollama1、下載Ollama安裝包https://ollama.com/download&#xff08;如果下載很慢 可以直接找我拿安裝包&#xff09;2、使用命令行安裝打開cmd 將下載的安裝包OllamaSetup.exe 放到想要安裝的目錄下。&#xff08;如果直接雙擊&#xff0c;會裝到C盤&#xff09;例如想裝到…

基于Python的新聞爬蟲:實時追蹤行業動態

引言 在信息時代&#xff0c;行業動態瞬息萬變。金融從業者需要實時了解政策變化&#xff0c;科技公司需要跟蹤技術趨勢&#xff0c;市場營銷人員需要掌握競品動向。傳統的人工信息收集方式效率低下&#xff0c;難以滿足實時性需求。Python爬蟲技術為解決這一問題提供了高效方…

阿里視頻直播解決方案VS(MediaMTX + WebRTC) 流媒體解決方案

背景&#xff1a; 公司采購了新的攝像頭&#xff0c;通過rtsp或者rtmp推流到云平臺&#xff0c;云平臺內部進行轉碼處理&#xff0c;客戶端使用HLS或HTTP-FLV播放&#xff0c;移動App可能使用HLS或私有SDK&#xff0c;超低延時則采用WebRTC。 技術選型&#xff1a; RTSP&…

day33:零基礎學嵌入式之網絡——TCP并發服務器

一、服務器1.服務器分類單循環服務器&#xff1a;只能處理一個客戶端任務的服務器并發服務器&#xff1a;可同時處理多個客戶端任務的服務器二、TCP并發服務器的構建1.如何構建&#xff1f;&#xff08;1&#xff09;多進程&#xff08;每一次創建都非常耗時耗空間&#xff0c;…

VR全景制作的流程?VR全景制作可以用在哪些領域?

VR全景制作的流程&#xff1f;VR全景制作可以用在哪些領域&#xff1f;VR全景制作&#xff1a;流程、應用與未來虛擬現實&#xff08;VR&#xff09;全景制作正迅速改變我們的感官體驗&#xff0c;使我們能夠身臨其境地探索虛擬世界&#xff0c;享受沉浸式的奇妙感受。那么&…

用LangChain重構客服系統:騰訊云向量數據庫+GPT-4o實戰

人們眼中的天才之所以卓越非凡&#xff0c;并非天資超人一等而是付出了持續不斷的努力。1萬小時的錘煉是任何人從平凡變成超凡的必要條件。———— 馬爾科姆格拉德威爾 目錄 一、傳統客服系統痛點與重構價值 1.1 傳統方案瓶頸分析 1.2 新方案技術突破點 二、系統架構設計&…

主要分布在腹側海馬體(vHPC)CA1區域(vCA1)的混合調諧細胞(mixed-tuning cells)對NLP中的深層語義分析的積極影響和啟示

腹側海馬體CA1區&#xff08;vCA1&#xff09;的混合調諧細胞&#xff08;mixed-tuning cells&#xff09;通過整合情感、社會關系、空間概念等多模態信息&#xff0c;形成動態的情景化語義表征&#xff0c;為自然語言處理&#xff08;NLP&#xff09;的深層語義分析提供了重要…

ESP32的ADF詳解:6. Audio Processing的API

一、Downmix 1. 核心功能 將基礎音頻流和新加入音頻流混合為單一輸出流&#xff0c;支持動態增益控制和狀態轉換。輸出聲道數與基礎音頻一致&#xff0c;新加入音頻自動轉換聲道匹配。2. 關鍵特性聲道處理 輸出聲道數 基礎音頻聲道數新加入音頻自動轉換聲道&#xff08;如立體…

Qt(基本組件和基本窗口類)

一、基本組件1. Designer設計師為什么要上來先將這個東西呢&#xff0c;這個是QT外置的設計界面的工具&#xff0c;沒啥用&#xff0c;所以了解一下。我們用的多的是QT內置的界面設計&#xff0c;只需要我們雙擊我們創建的項目的.ui文件就可以進入這個界面&#xff0c;你對界面…

docker與k8s的容器數據卷

Docker容器數據卷 特性 docker鏡像由多個只讀層疊加而成&#xff0c;啟動容器時&#xff0c;Docker會加載只讀鏡像層并在鏡像棧頂部添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件&#xff0c;那么該文件將會從讀寫層下面的只讀層復制到讀寫層&#xff0c;該…

自然語言處理技術應用領域深度解析:從理論到實踐的全面探索

1. 引言:自然語言處理的技術革命與應用前景 自然語言處理(Natural Language Processing,NLP)作為人工智能領域的核心分支,正在以前所未有的速度改變著我們的數字化生活。從最初的規則基礎系統到如今基于深度學習的大語言模型,NLP技術經歷了從理論探索到實際應用的深刻變…

OpenGLRender開發記錄(二): 陰影(shadowMap,PCF,PCSS)

目錄已實現功能陰影shadowMapPCFPCSS實現shadowMapPCFPCSS陰影GitHub主頁&#xff1a;https://github.com/sdpyy1 OpenGLRender:https://github.com/sdpyy1/CppLearn/tree/main/OpenGL 已實現功能 除了上次實現IBL之外&#xff0c;項目目前新增了imGUI的渲染&#xff0c;更方便…