【深度解析】Java高級并發模式與實踐:從ThreadLocal到無鎖編程,全面避坑指南!

🔍 一、ThreadLocal:線程隔離的利器與內存泄露陷阱

底層原理揭秘:
每個線程內部維護ThreadLocalMap,Key為弱引用的ThreadLocal對象,Value為存儲的值。這種設計導致了經典內存泄露場景:

// 典型應用:用戶會話存儲
public class UserContextHolder {private static final ThreadLocal<User> currentUser = new ThreadLocal<>();public static void set(User user) {currentUser.set(user);}public static User get() {return currentUser.get();}// 關鍵!必須清理public static void clear() {currentUser.remove(); }
}

核心應用場景

  • 上下文信息傳遞:用戶 Session、事務 ID、請求鏈路追蹤 ID,避免在方法間顯式傳遞參數。
  • 線程不安全工具類副本:如 SimpleDateFormat(替代方案是使用 ThreadLocal 或 JDK 8 的 DateTimeFormatter)。
  • 性能優化:避免重復創建對象(如數據庫連接的非線程安全包裝類)。

關鍵實踐與風險

  • 內存泄露
    • 根本原因:線程池中的線程長期存活,ThreadLocal 值未被清除 → 值對象(強引用)無法回收。
    • 解決方案:
      • 使用 ThreadLocal.remove() 顯式清理(如 finally 塊中)。
      • 使用 WeakReferenceThreadLocalMap 的 Key 是弱引用,但 Value 仍是強引用)。
  • 最佳實踐
    • 始終在 try-finally 中清理
      userContext.set(currentUser);
      try {// 業務邏輯
      } finally {userContext.remove(); // 強制清除
      }
      
    • 避免存儲大對象(易引發 OOM)。

?? 高并發下的特殊場景:

  • 線程池中線程復用會導致信息串用
  • InheritableThreadLocal實現父子線程傳遞
  • Spring框架中RequestContextHolder的實現原理

🧱 二、不變性(Immutability):并發安全的終極武器

實現方式

  1. 類用 final 修飾(防繼承覆蓋)。
  2. 所有字段用 final 修飾(構造后不可變)。
  3. 不暴露修改方法(如 setter)。
  4. 返回防御性拷貝(如集合類返回 Collections.unmodifiableList)。

優勢

  • 天然線程安全:無競態條件,無需同步。
  • 簡化代碼:無需考慮鎖和并發控制。
  • 安全共享:對象可在多線程間自由傳遞。

經典案例

  • StringBigDecimaljava.time 包中的日期類。
  • 自定義不可變對象:
    // 典型的不可變類
    public final class ImmutableConfig {private final int timeout;private final List<String> servers; // 引用類型需特殊處理public ImmutableConfig(int timeout, List<String> servers) {this.timeout = timeout;this.servers = Collections.unmodifiableList(new ArrayList<>(servers));}// 返回不可修改的副本public List<String> getServers() {return Collections.unmodifiableList(servers);}
    }
    

性能對比實驗

方案10萬次讀(ms)10萬次寫(ms)內存占用
不可變對象45-中等
synchronized210185
ConcurrentHashMap6572

?? 三、六大并發設計模式實戰

模式核心思想實現工具
生產者-消費者解耦生產與消費邏輯BlockingQueue (如 LinkedBlockingQueue)
線程池模式復用線程,避免頻繁創建銷毀開銷ExecutorService (如 ThreadPoolExecutor)
工作竊取模式平衡負載,空閑線程偷取其他隊列任務ForkJoinPool
主從/領導者-跟隨者主線程分配任務,從線程執行并返回結果CompletableFuture + 線程池
流水線模式任務分階段處理,類似工廠流水線PhaserCyclicBarrier
不變對象模式無變化則無需同步finalRecord類型 、不可變集合、防御性拷貝
🔥 1. 生產者-消費者模式(解耦神器)

適用場景:日志處理、消息隊列、訂單系統

// 實戰代碼示例
BlockingQueue<Log> queue = new ArrayBlockingQueue<>(100); // 有界隊列防OOM// 生產者線程池
ExecutorService producers = Executors.newCachedThreadPool();
producers.execute(() -> {while (isRunning) {Log log = generateLog(); // 模擬日志生成queue.put(log);  // 隊列滿時自動阻塞}
});// 消費者線程池(4個消費者)
ExecutorService consumers = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {consumers.execute(() -> {while (isRunning) {Log log = queue.take(); // 隊列空時阻塞uploadToES(log);  // 上傳到Elasticsearch}});
}

最佳實踐

  1. 使用new ArrayBlockingQueue<>(capacity)避免無界隊列導致OOM
  2. 生產/消費者線程分離管理
  3. 毒丸(Poison Pill)終止策略:
    queue.put(POISON_PILL); // 發送終止信號
    // 消費者收到特殊對象時退出
    

?? 2. 線程池模式(資源復用典范)

四類線程池適用場景

// 1. 固定大小線程池(CPU密集型)
ExecutorService fixedPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());// 2. 緩存線程池(短時異步任務)
ExecutorService cachedPool = Executors.newCachedThreadPool(); // 注意OOM風險!// 3. 定時任務線程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
scheduledPool.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);// 4. 工作竊取線程池(ForkJoinPool)
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
forkJoinPool.submit(() -> { /* 可分拆任務 */ });

自定義線程池黃金參數

ThreadPoolExecutor customPool = new ThreadPoolExecutor(4, // 核心線程數16, // 最大線程數60, TimeUnit.SECONDS, // 空閑回收new ArrayBlockingQueue<>(200), // 有界隊列new CustomThreadFactory(), // 命名線程new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略:調用者執行
);

🧩 3. 工作單元模式(任務分治)

ForkJoin框架實戰

// 計算1~n的平方和
class SumTask extends RecursiveTask<Long> {private final int start;private final int end;@Overrideprotected Long compute() {if (end - start <= 1000) { // 小任務直接計算long sum = 0;for (int i = start; i <= end; i++) sum += i * i;return sum;}// 大任務拆分(二分法)int mid = (start + end) / 2;SumTask leftTask = new SumTask(start, mid);SumTask rightTask = new SumTask(mid+1, end);leftTask.fork(); // 異步執行子任務return rightTask.compute() + leftTask.join(); // 合并結果}
}// 調用示例
ForkJoinPool pool = new ForkJoinPool();
long result = pool.invoke(new SumTask(1, 100_000));

場景:大數據處理、歸并排序、復雜計算


👑 4. 主從/領導者-跟隨者模式

分布式計算實現

// Leader節點(任務分配)
List<Future<Result>> futures = new ArrayList<>();
for (Task task : allTasks) {futures.add(executor.submit(() -> worker.execute(task)));
}// 結果聚合
List<Result> results = new ArrayList<>();
for (Future<Result> future : futures) {results.add(future.get()); // 阻塞等待所有結果
}// Worker節點示例
class Worker implements Callable<Result> {public Result call() {return process(ThreadLocalRandom.current().nextInt()); }
}

優化技巧

  1. 使用CompletionService實現完成順序獲取結果:
    CompletionService<Result> cs = new ExecutorCompletionService<>(executor);
    cs.submit(worker);
    Result r = cs.take().get(); // 獲取最先完成的任務
    
  2. 批量任務拆分執行(MapReduce思想)

🧱 5. 不變對象模式(安全基石)

深度不變實現

public final class ImmutableConfig {private final int timeout;private final List<String> urls;  // 引用類型特殊處理public ImmutableConfig(int timeout, List<String> sourceUrls) {this.timeout = timeout;// 防御性復制 + 不可變包裝this.urls = Collections.unmodifiableList(new ArrayList<>(sourceUrls));}// 返回不可修改的副本public List<String> getUrls() {return Collections.unmodifiableList(new ArrayList<>(urls));}// 構建器模式(可選)public static class Builder {private int timeout;private List<String> urls = new ArrayList<>();public Builder setTimeout(int t) { this.timeout = t; return this; }public Builder addUrl(String url) { urls.add(url); return this; }public ImmutableConfig build() {return new ImmutableConfig(timeout, urls);}}
}

使用場景

  • 配置參數
  • DTO數據傳輸
  • 并發緩存鍵值

🔁 6. 流水線模式(任務分段)

Phase分階段處理器

// 三階段處理器
public class VideoProcessPipeline {private final ExecutorService[] stages = new ExecutorService[3];public VideoProcessPipeline() {// 每階段獨立線程池stages[0] = Executors.newFixedThreadPool(2); // 解碼stages[1] = Executors.newFixedThreadPool(4); // 濾鏡stages[2] = Executors.newSingleThreadExecutor(); // 編碼}public void process(Video video) {// Phase 1: 解碼CompletableFuture<Frame> stage1 = CompletableFuture.supplyAsync(() -> decode(video), stages[0]);// Phase 2: 濾鏡處理(依賴階段1)CompletableFuture<Frame> stage2 = stage1.thenApplyAsync(frame -> applyFilters(frame), stages[1]);// Phase 3: 編碼輸出(依賴階段2)stage2.thenAcceptAsync(frame -> encodeAndSave(frame), stages[2]);}
}

特點

  1. 階段間通過隊列傳遞數據
  2. 可獨立擴展各階段處理能力
  3. 支持復雜業務處理流程

💡 設計模式選型矩陣
場景推薦模式性能要點
任務分發生產者-消費者隊列容量控制
計算密集型工作竊取(ForkJoin)任務拆分粒度
I/O密集型領導者-跟隨者異步回調
配置管理不變對象防御性拷貝
流程化業務流水線階段線程數優化
資源復用線程池拒絕策略選擇

🛠 實戰性能調優Tips
  1. 線程池監控:通過JMX或Spring Boot Actuator監控隊列堆積
    ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
    int queueSize = pool.getQueue().size();
    
  2. 工作竊取優化:合理設置閾值避免過度拆分
    if (end - start <= THRESHOLD) {...} // 根據實驗確定最佳閾值
    
  3. 流水線瓶頸定位:使用Arthas監控各階段耗時
    trace com.example.VideoProcessPipeline applyFilters
    

🚨 避坑警告:分布式場景下使用領導者-跟隨者時,必須實現Leader選舉機制(如ZooKeeper Curator)!


💥 四、無鎖編程:CAS原理與ABA問題深度剖析

核心:CAS (Compare-And-Swap)

  • 底層原理:CPU 原子指令(如 x86 的 CMPXCHG),比較內存值是否等于預期值,是則更新。
  • Java 實現
    • AtomicIntegerAtomicReference 等原子類。
    • Unsafe 類(底層操作,JDK 內部 API,不推薦直接使用)。

無鎖數據結構示例

AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // CAS 實現自增

挑戰與陷阱

  • ABA問題
    值從 A→B→A,CAS 無法感知中間變化。
    解決方案AtomicStampedReference(附加版本戳)。
  • 自旋開銷:競爭激烈時 CPU 空轉。
  • 實現復雜度:非阻塞算法設計極其困難(如無鎖隊列)。

Java原子類實現揭秘

// AtomicInteger自增源碼解析
public final int incrementAndGet() {int prev, next;do {prev = get(); // 當前值next = prev + 1;} while (!compareAndSet(prev, next)); // CAS自旋return next;
}

ABA問題復現

線程1讀取值A
線程2修改A->B
線程2修改B->A
線程1執行CAS: 預期值A成功

解決方案對比

方案實現類優點缺點
版本戳AtomicStampedReference徹底解決ABA額外內存開銷
計數器AtomicMarkableReference實現簡單可能溢出
不變對象-根本解決需要重構代碼

? 五、高并發性能調優實戰工具箱

關鍵指標

  • 吞吐量:單位時間處理的任務數(TPS/QPS)。
  • 延遲:單次請求響應時間(P99 值更重要)。
  • CPU利用率:過高可能由鎖競爭或頻繁 GC 引起。

監控工具鏈

  1. 線程分析
    • jstack:獲取線程棧,檢測死鎖(輸出中搜索 deadlock)。
    • jcmd <PID> Thread.print:替代 jstack
  2. 運行時監控
    • JVisualVM/JConsole:圖形化查看線程狀態、鎖等待。
    • Java Mission Control (JMC):低開銷線上診斷。
  3. GC 診斷
    • jstat -gcutil <PID> 1000:每秒輸出 GC 統計。
    • -Xlog:gc*:JDK 9+ 的詳細 GC 日志。
  4. 高級診斷
    • Arthas:在線熱更新、監控方法調用耗時。
    • async-profiler:低開銷 CPU/內存火焰圖。

優化策略

  • 減少鎖競爭
    • 縮小同步范圍(同步塊 vs 同步方法)。
    • 分離鎖(鎖拆分、鎖分段),如 ConcurrentHashMap 的分段鎖。
    • 讀寫分離:ReentrantReadWriteLockStampedLock
  • 線程池調優
    • 核心參數corePoolSizemaxPoolSizeworkQueue(避免無界隊列!)。
    • 拒絕策略:根據業務選 AbortPolicy(拋異常)或 CallerRunsPolicy(回退到調用線程)。
  • 非阻塞 I/O
    • 使用 Netty、Undertow 等框架,結合 NIOEventLoopGroup
  • 緩存行填充
    • 偽共享:多線程修改同一緩存行導致緩存失效。
    • 解決:@sun.misc.Contended(JDK 8+)或手動填充字段(Java 對象頭占用 12-16 字節)。
      class Data {@Contended volatile long value1; // 避免偽共享
      }
      

線程池參數黃金公式

  • CPU密集型:corePoolSize = CPU核數 + 1
  • IO密集型:corePoolSize = CPU核數 * 2 + 1
  • 隊列選擇:
    new ThreadPoolExecutor(8, 16, 60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(200), // 有界隊列防OOMnew CustomRejectPolicy()       // 自定義拒絕策略
    );
    

🚫 六、并發陷阱與避坑指南

高頻陷阱

陷阱類型解決方案/規避方案
死鎖1. 固定鎖順序
2. tryLock(timeout)
3. 監控告警(如 JVM 死鎖檢測)
資源耗盡1. 線程池使用有界隊列
2. 限制最大線程數(避免 newCachedThreadPool 濫用)
上下文切換過多減少阻塞調用,優化線程數(IO 密集型:2N+1,CPU 密集型:N+1)
不安全的發布不在構造器中暴露 this 引用(避免回調導致訪問未初始化對象)
線程中斷忽略正確處理 InterruptedException(恢復中斷狀態 Thread.currentThread().interrupt()
過度同步優先用并發容器(ConcurrentHashMap)代替手動同步 Collections.synchronizedMap
  1. 死鎖四大條件破局

    if (lock1.tryLock(100, MILLISECONDS)) {try {if (lock2.tryLock(100, MILLISECONDS)) {try {// 業務邏輯} finally { lock2.unlock(); }}} finally { lock1.unlock(); }
    }
    
  2. 線程中斷的正確處理

    try {while (!Thread.interrupted()) {// 可中斷操作}
    } catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢復中斷狀態
    }
    
  3. 資源泄漏防范清單

    • 線程池必須用shutdownNow()強制關閉
    • 數據庫連接池配合removeAbandonedTimeout
    • 文件操作必須放在try-with-resources
  4. 上下文切換優化技巧

    • Linux服務器設置/proc/sys/kernel/sched_child_runs_first
    • 禁用-XX:+UseSpinning自旋鎖
    • NUMA架構綁定CPU核心

黃金法則

  1. KISS原則:優先使用 java.util.concurrent 內置工具,避免重復造輪子。
  2. 理解業務并發模型:區分 CPU 密集型 vs IO 密集型任務,針對性優化。
  3. 防御式編程:對共享狀態持有高度警惕,默認設計為不可變對象。
  4. 監控先行:高并發系統需配備實時監控(線程池隊列積壓、GC 暫停時間)。

💎 總結:并發編程三大黃金原則

  1. 優先不變性:80%的并發問題可通過不可變對象解決
  2. 工具優于造輪子java.util.concurrent覆蓋90%場景
  3. 監控大于優化:沒有Metrics的調優就是耍流氓

實戰建議:在壓測環境中,使用-XX:+PreserveFramePointer參數配合async-profiler,能精準定位鎖競爭熱點!

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

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

相關文章

使用存儲型 XSS 竊取 cookie 并發送到你控制的服務器

&#x1f9ea; 第一步&#xff1a;準備監聽服務接收 cookie 在你的本機&#xff08;非容器&#xff09;或 DVWA 所在主機運行以下 Python 監聽代碼&#xff0c;用于接收竊取的 cookie&#xff1a; 啟動 HTTP 接收服務 # 在本機終端運行&#xff0c;監聽 8081 端口&#xff0…

WebDebugX和多工具組合的移動端調試流程構建:一個混合App項目的實踐案例

前段時間參與了一個跨平臺的醫療服務 App 項目&#xff0c;整體架構采用 Flutter 封裝原生模塊&#xff0c;部分功能模塊嵌套 WebView 加載 H5 頁面。開發過程中我們頻繁遇到 Web 頁面在移動端表現異常的問題&#xff0c;比如樣式錯亂、請求失敗、性能延遲等&#xff0c;而這些…

圖形編輯器基于Paper.js教程29:基于圖層的所有矢量圖元的填充規則實現

背景 在lightburn中&#xff0c;對于填充圖層&#xff0c;有這樣一個隱藏的邏輯&#xff0c;那就是&#xff0c;在加工時&#xff0c;填充規則是以填充圖層的所有元素進行計算的&#xff0c;什么意思那&#xff1f; 如果你在填充圖層中畫了兩個圖形&#xff0c;一個圓&#xf…

Python 函數實戰指南:提升編程效率的實用技巧

在 Python 編程的世界里&#xff0c;函數是構建高效代碼的基石。掌握實用的函數技巧不僅能讓代碼更加簡潔優雅&#xff0c;還能顯著提升開發效率。我們一起將結合實際案例&#xff0c;深入剖析 Python 函數的使用技巧&#xff0c;幫助開發者在日常開發中事半功倍。 一、基礎函數…

OPenCV CUDA模塊圖形變換----構建透視變換映射表函數buildWarpPerspectiveMaps()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數用于構建一個透視變換&#xff08;Perspective Transform&#xff09;的映射表&#xff08;xmap / ymap&#xff09;&#xff0c;可用于后…

tcping工具使用指南

tcping是一個用于測試TCP端口連通性的工具&#xff0c;它類似于傳統的ping命令&#xff0c;但工作在傳輸層(TCP)而不是網絡層(ICMP)。 基本功能 tcping的主要功能包括&#xff1a; 測試目標主機特定TCP端口是否開放 測量TCP連接建立時間 統計丟包率和響應時間 安裝方法 …

CSP 2024 入門級第一輪(88.5)

4. 以下哪個序列對應數字 00 至 88 的 44 位二進制格雷碼&#xff08;Gray code&#xff09;&#xff1f;&#xff08; &#xff09; A. 0000, 0001, 0011, 0010, 0110, 0111, 0101, 1000 B. 0000, 0001, 0011, 0010, 0110, 0111, 0100, 0101 C. 0000, 0001, 0011, 0010, …

三菱FX-5U系列入門到精通

第2章 中間繼電器 繼電器工作模式:線圈得電,常開觸點閉合,常閉觸點斷開。總結:中間繼電器線圈電壓分為:24VDC 110VAC 220VAC 380VAC PLC控制柜中常用的是24VDC比較多,而動力電柜中或者控制風機水泵的電柜中220VAC比較多。大部分選擇24VDC,然后用觸點控制220或者380,說白…

簡歷模板1——王明 | 高級數據挖掘工程師 | 5年經驗

王明 | 高級數據挖掘工程師 | 5年經驗 &#x1f4f1; (86) 189-xxxx-xxxx | &#x1f4e7; wangmingemail.com | &#x1f4cd; 深圳市 &#x1f4bb; GitHub | &#x1f454; LinkedIn &#x1f4bc; 工作經歷 ?科技前沿集團 | 高級數據挖掘工程師 &#x1f4c5; 2021.06 …

【JVM】- 內存模式

Java內存模型&#xff1a;JMM&#xff08;Java Memory Model&#xff09;&#xff0c;定義了一套在多線程環境下&#xff0c;讀寫共享數據&#xff08;成員變量、數組&#xff09;時&#xff0c;對數據的可見性&#xff0c;有序性和原子性的規則和保障。 原子性 問題分析 【問…

AQS獨占模式——資源獲取和釋放源碼分析

AQS資源獲取&#xff08;獨占模式&#xff09; Node節點類 static final class Node {//標記當前節點的線程在共享模式下等待。static final Node SHARED new Node();//標記當前節點的線程在獨占模式下等待。static final Node EXCLUSIVE null;//waitStatus的值&#xff0c…

壓測過程中TPS上不去可能是什么原因

進行性能分析 接口沒有報錯或者錯誤率低于1%&#xff0c;繼續增加并發還是一樣&#xff0c;這個時候需要考慮幾點 1.是否觸發限流&#xff0c;比如waf、Nginx等情況&#xff0c;有沒有一些限流的情況&#xff0c;如果觸發了限流&#xff0c;請求是沒有達到后端的&#xff0c;所…

Golang 解大整數乘法

文章目錄 Golang 解大整數乘法問題描述&#xff1a;LeetCode 43. 字符串相乘思路Golang 代碼 Golang 解大整數乘法 在初學 C 語言的時候&#xff0c;我們一定接觸過“字符串相加”或“字符串相乘”之類的問題&#xff0c;對于初學者而言&#xff0c;這類問題的難度一般來說是比…

web3-區塊鏈的技術安全/經濟安全以及去杠桿螺旋(經濟穩定)

web3-區塊鏈的技術安全/經濟安全以及去杠桿螺旋&#xff08;經濟穩定&#xff09; 三個基本設計問題 技術安全 在技術結構中對其進行原子級的、瞬時利用&#xff08;無風險&#xff09; 無風險&#xff0c;因為攻擊者的結果還是二進制的&#xff1a; 只會是攻擊成功 獲利或…

Java多線程通信:wait/notify與sleep的深度剖析(時序圖詳解)

在Java多線程編程中&#xff0c;線程間的通信與協作是實現復雜并發邏輯的關鍵。wait()、notify()以及sleep()方法作為線程控制的重要工具&#xff0c;有著各自獨特的使用場景與規則。本文將深入探討wait()和notify()的協作機制&#xff0c;以及sleep()的阻塞特性&#xff0c;同…

關于使用EasyExcel、 Vue3實現導入導出功能

后端部分: 其中查詢數據的服務省略 1、引用 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version></dependency> 2、controller package com.rs.cphs.sys.controller;i…

機器學習中的數據準備關鍵技術

有效的數據準備對于構建強大的機器學習模型至關重要。本文檔總結并闡述了為監督和非監督學習任務準備數據的關鍵技術。 1. 理解數據類型 有兩種數據類型。定性數據描述對象的特征&#xff0c;而定量數據描述對象的數量。 定性&#xff08;分類&#xff09;數據 名義&#x…

深度學習——基于卷積神經網絡實現食物圖像分類【3】(保存最優模型)

文章目錄 引言一、項目概述二、環境配置三、數據預處理3.1 數據轉換設置3.2 數據集準備 四、自定義數據集類五、CNN模型架構六、訓練與評估流程6.1 訓練函數6.2 評估與模型保存 七、完整訓練流程八、模型保存與加載8.1 保存模型8.2 加載模型 九、優化建議十、常見問題解決十一、…

《棒球百科》棒球怎么玩·棒球9號位

用最簡單的方式介紹棒球的核心玩法和規則&#xff0c;完全零基礎也能看懂&#xff1a; 一句話目標 進攻方&#xff1a;用球棒把球打飛&#xff0c;然后拼命跑完4個壘包&#xff08;逆時針繞一圈&#xff09;得分。 防守方&#xff1a;想盡辦法讓進攻方出局&#xff0c;阻止他…

語言模型是怎么工作的?通俗版原理解讀!

大模型為什么能聊天、寫代碼、懂醫學&#xff1f; 我們從四個關鍵模塊&#xff0c;一步步拆開講清楚 &#x1f447; ? 模塊一&#xff1a;模型的“本事”從哪來&#xff1f;靠訓練數據 別幻想它有意識&#xff0c;它的能力&#xff0c;全是“喂”出來的&#xff1a; 吃過成千…