Java 線程詳解 --線程概念、線程池、線程同步與安全機制

一、Java線程的概念

Java 線程的本質:每個線程對應一個操作系統線程,由操作系統調度。JVM 通過調用操作系統 API(如 Linux 的 pthread)創建線程。

關鍵點
? 用戶態與內核態:線程調度依賴操作系統(內核級線程),能直接利用多核 CPU。
? 線程生命周期:新建 → 就緒 → 運行 → 阻塞 → 終止。
? JVM 線程模型:每個 Java 線程對應一個 Thread 對象,通過 start() 觸發操作系統線程的創建。


二、線程的使用方法

方式 1:繼承 Thread 類(簡單但不夠靈活)
class MyThread extends Thread {@Overridepublic void run() {System.out.println("線程執行: " + Thread.currentThread().getName());}
}// 使用
MyThread t = new MyThread();
t.start(); // 注意:必須調用 start(),而不是直接 run()
方式 2:實現 Runnable 接口(推薦,避免單繼承限制)
class MyTask implements Runnable {@Overridepublic void run() {System.out.println("任務執行: " + Thread.currentThread().getName());}
}// 使用
Thread t = new Thread(new MyTask());
t.start();
方式 3:帶返回值的 Callable(適合需要結果的任務)

? Callable:帶返回值的任務(像“下單”),比如 Callable<String> 表示這個任務最終會返回一個 String
? Future:代表異步任務的“憑證”(像“訂餐小票”),憑它未來可以取結果。

以訂餐流程舉例:

  1. 提交任務:你去餐廳點了一份炒飯,服務員給你一張小票Future)。
  2. 后廚做菜:廚師(線程池中的線程)開始炒飯(執行 Callable)。
  3. 等待結果:你可以干其他事情(不阻塞主線程),也可以隨時拿小票問:“好了沒?”(future.isDone())。
  4. 取回結果:當炒飯做好后,憑小票取餐(future.get() 拿到返回值)。

Future底層實現原理:

  1. 狀態跟蹤Future 內部維護任務狀態:
    ? 未完成:任務還在執行。
    ? 已完成:任務正常結束,保存返回值。
    ? 已取消:任務被中斷。
    ? 異常結束:保存拋出的異常。

  2. 阻塞獲取:當調用 future.get() 時:
    ? 如果任務已完成 → 直接返回結果。
    ? 如果未完成 → 當前線程阻塞等待,直到任務完成(內部通過 wait/notify 機制實現)。

  3. 結果存儲:任務完成后,返回值(或異常)會被存入 Future 內部的成員變量,供后續讀取。

代碼示例:

import java.util.concurrent.*;public class FutureExample {public static void main(String[] args) throws Exception {// 1. 創建線程池(后廚)ExecutorService executor = Executors.newSingleThreadExecutor();// 2. 提交 Callable 任務(下單炒飯)Future<String> future = executor.submit(new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(2000); // 模擬炒飯需要2秒return "揚州炒飯做好了!";}});System.out.println("提交任務后,主線程繼續做其他事情...");// 3. 檢查是否完成(非阻塞)if (future.isDone()) {System.out.println("任務已經完成!");} else {System.out.println("任務還在進行中...");}// 4. 阻塞獲取結果(類似等待取餐)String result = future.get(); // 這里會阻塞,直到任務完成System.out.println("取到結果:" + result);executor.shutdown(); // 關閉線程池(后廚下班)}
}

輸出:

提交任務后,主線程繼續做其他事情...
任務還在進行中...
(等待2秒后)
取到結果:揚州炒飯做好了!
  1. 異常處理
    如果任務中拋出異常,future.get() 會拋出 ExecutionException,可通過 getCause() 獲取原始異常:
try {future.get();
} catch (ExecutionException e) {System.out.println("任務出錯:" + e.getCause());
}
  1. 超時控制
    避免無限等待,可以設置超時時間:
String result = future.get(3, TimeUnit.SECONDS); // 最多等3秒
  1. 取消任務
    如果不想等了,可以取消任務:
future.cancel(true); // true表示嘗試中斷正在執行的任務

三、Java 線程池機制詳解

線程池的核心思想

? 復用線程:避免頻繁創建/銷毀線程的開銷(類似餐廳固定幾個服務員服務所有顧客,而不是每來一個顧客就雇傭新服務員)。
? 資源管控:通過隊列緩沖任務,防止系統過載(類似餐廳的等候區,避免人太多擠爆店面)。


線程池的四大核心參數
ThreadPoolExecutor(int corePoolSize,      // 核心線程數(常駐員工)int maximumPoolSize,   // 最大線程數(臨時工上限)long keepAliveTime,    // 空閑線程存活時間(臨時工多久沒活就解雇)TimeUnit unit,         // 時間單位BlockingQueue<Runnable> workQueue, // 任務隊列(等候區座位數)RejectedExecutionHandler handler   // 拒絕策略(人滿時怎么處理新顧客)
)

參數詳解:

  1. corePoolSize:核心線程即使空閑也不會被銷毀(除非設置 allowCoreThreadTimeOut)。
  2. maximumPoolSize:當隊列滿時,允許創建的最大線程數(核心線程 + 臨時線程)。
  3. workQueue:常用隊列類型:
    ? ArrayBlockingQueue:有界隊列(固定容量)。
    ? LinkedBlockingQueue:無界隊列(默認 Integer.MAX_VALUE,慎用易內存溢出)。
    ? SynchronousQueue:不存儲任務,直接移交(適合瞬時高并發)。
  4. 拒絕策略(當隊列和線程池全滿時):
    ? AbortPolicy:拋異常(默認)。
    ? CallerRunsPolicy:讓提交任務的線程自己執行。
    ? DiscardPolicy:默默丟棄新任務。
    ? DiscardOldestPolicy:丟棄隊列最舊的任務,再嘗試提交。

合理設置線程數
? CPU密集型:線程數 ≈ CPU核數(避免過多上下文切換)。
? IO密集型:線程數 ≈ CPU核數 * 2(或更高,因線程常阻塞在IO)。

監控線程池狀態

// 查看活躍線程數
int activeCount = executor.getActiveCount(); 
// 查看任務隊列大小
int queueSize = executor.getQueue().size();

線程池的工作流程
                ↗ 核心線程有空 → 立即執行
任務提交 → 檢查核心線程↘ 核心線程忙 → 入隊列 → 隊列滿? → 否 → 等待↘ 是 → 創建臨時線程 → 超過最大數? → 是 → 拒絕

常用線程池(通過 Executors 工廠創建)
1. FixedThreadPool(固定大小團隊)
ExecutorService fixedPool = Executors.newFixedThreadPool(4); // 4個核心線程

? 特點:核心線程=最大線程,無臨時線程,使用無界隊列(LinkedBlockingQueue)。
? 適用場景:已知并發量且任務耗時較長(如后臺計算)。

2. CachedThreadPool(彈性團隊)
ExecutorService cachedPool = Executors.newCachedThreadPool(); 

? 特點:核心線程=0,最大線程=Integer.MAX_VALUE,空閑線程60秒回收,使用 SynchronousQueue(直接移交任務)。
? 適用場景:短時高頻小任務(如HTTP請求處理)。

3. SingleThreadExecutor(單人團隊)
ExecutorService singlePool = Executors.newSingleThreadExecutor();

? 特點:核心線程=最大線程=1,無界隊列,保證任務順序執行。
? 適用場景:需要順序執行的任務(如日志寫入)。

4. ScheduledThreadPool(計劃任務團隊)
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
// 延遲3秒執行
scheduledPool.schedule(() -> System.out.println("Run after 3s"), 3, TimeUnit.SECONDS);
// 固定頻率執行(每隔1秒)
scheduledPool.scheduleAtFixedRate(() -> System.out.println("Run every 1s"), 0, 1, TimeUnit.SECONDS);

? 特點:支持定時、周期性任務。
? 適用場景:心跳檢測、定時數據同步。


5. 自定義線程池
public class ThreadPoolDemo {public static void main(String[] args) {// 創建線程池:2核心線程,5最大線程,10容量隊列,拒絕策略拋異常ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),new ThreadPoolExecutor.AbortPolicy());// 提交20個任務(測試隊列滿時的擴容)for (int i = 0; i < 20; i++) {final int taskId = i;try {executor.submit(() -> {System.out.println("任務 " + taskId + " 由線程 " + Thread.currentThread().getName() + " 執行");try { Thread.sleep(1000); } catch (InterruptedException e) {}});} catch (RejectedExecutionException e) {System.out.println("任務 " + taskId + " 被拒絕!");}}executor.shutdown(); // 平滑關閉(等待已有任務完成)}
}

輸出分析
? 前2個任務由核心線程立即執行。
? 接下來的10個任務進入隊列。
? 當隊列滿后(10個),創建3個臨時線程(總線程數=5)。
? 第18個任務提交時,線程數已達最大(5),隊列滿(10),觸發拒絕策略拋異常。

場景推薦線程池參數要點
長期穩定并發任務FixedThreadPool核心線程數=最大線程數,隊列容量適中
短期突發小任務CachedThreadPool注意防止無限創建線程(適合可控的短任務)
單線程順序執行SingleThreadExecutor替代手動創建線程,保證順序性
定時/周期性任務ScheduledThreadPool指定延遲和周期
高并發自定義需求ThreadPoolExecutor根據業務特點調整核心參數

線程池關閉方法
  1. shutdown():平滑關閉,不再接受新任務,等待已有任務完成。
  2. shutdownNow():立刻停止所有任務,返回未執行的任務列表。
List<Runnable> unfinishedTasks = executor.shutdownNow();

四、線程同步與安全,原理、用法及示例

在多線程環境下,當多個線程同時訪問共享資源(如變量、文件、數據庫)時,可能導致數據不一致或邏輯錯誤。線程同步的目的是協調線程間的執行順序,確保線程安全。

詳細參考:https://blog.csdn.net/gengzhikui1992/article/details/147230900?spm=1001.2014.3001.5501

常見同步方式及底層原理
1. synchronized 關鍵字:

? 原理:基于對象的內置鎖(Monitor),每個對象關聯一個Monitor。
執行synchronized代碼時,線程需獲取對象的Monitor鎖:
? 成功則持有鎖,執行代碼。
? 失敗時線程進入鎖的等待隊列(EntrySet),阻塞等待喚醒。
? 用法

// 同步方法
public synchronized void safeMethod() { /* ... */ }// 同步代碼塊
public void someMethod() {synchronized (this) { // 鎖對象為當前實例// 臨界區代碼}
}

? 示例

class Counter {private int count = 0;public synchronized void increment() {count++; // 原子操作}
}

解析synchronized確保同一時刻僅一個線程執行increment()方法。


2. ReentrantLock 可重入鎖:

? 原理:基于AQS(AbstractQueuedSynchronizer),維護一個CLH隊列管理等待線程。
支持可重入性(同一線程可多次加鎖)和公平性(可選)。
? 用法

private final ReentrantLock lock = new ReentrantLock();public void safeMethod() {lock.lock();  // 手動加鎖try {// 臨界區代碼} finally {lock.unlock(); // 必須手動釋放}
}

? 示例(帶超時):

if (lock.tryLock(1, TimeUnit.SECONDS)) { // 嘗試1秒內獲取鎖try { /* ... */ } finally { lock.unlock(); }
} else { // 超時處理 }

優勢:比synchronized更靈活,支持嘗試鎖、公平鎖等。

特性synchronizedReentrantLock
鎖的獲取方式自動獲取和釋放(JVM管理)手動 lock()unlock()(需寫finally)
可中斷性不支持(阻塞時無法中斷)支持 lockInterruptibly()
超時機制不支持(只能阻塞等待)支持 tryLock(timeout)
公平鎖僅非公平鎖支持公平和非公平(構造參數控制)
條件變量只能綁定一個條件(wait()/notify()可創建多個條件(newCondition()
性能JDK6后優化后性能接近高并發競爭時性能更好
代碼復雜度簡單(自動管理)復雜(需手動釋放,易忘)
鎖的可見性通過JVM內存模型保證基于AQS的volatile變量保證

? synchronized 的優勢:簡單、安全、自動釋放鎖,適合快速開發。
? ReentrantLock 的優勢:靈活、功能強大,適合需要超時、中斷、公平鎖等復雜場景。

最終建議:優先用 synchronized,遇到它無法滿足需求時再考慮 ReentrantLock


3. volatile 變量:

多線程環境下,變量操作可能引發兩種問題:

  1. 可見性問題:A線程修改了變量,B線程看不到最新值。
  2. 原子性問題:看似一步的操作(如 i++),實際分三步(讀-改-寫),中間可能被其他線程打斷。

volatile 變量:解決了可見性問題,原理:通過內存屏障禁止指令重排序,確保變量的修改對所有線程立即可見(不保證原子性)。

? 強制讀寫主內存volatile 變量修改后,其他線程立即可見。
? 禁止指令重排序:確保代碼執行順序符合預期。

使用場景
適合做 狀態標志(如開關控制),不涉及復雜計算。

public class Server {private volatile boolean isRunning = true;  // 狀態標志public void stop() {isRunning = false;  // 修改后,其他線程立即可見}public void run() {while (isRunning) {  // 循環讀取最新值// 處理請求...}}
}

局限性
? 不保證原子性volatile 無法解決 i++ 這種非原子操作的問題。

volatile int count = 0;
count++;  // 實際分三步:讀 -> 改 -> 寫(線程不安全!)

4. 原子類(Atomic Classes):解決原子性問題

? 封裝原子操作:通過 CPU 的 CAS(Compare-And-Swap) 指令,保證操作的原子性。
? 無需加鎖:性能優于 synchronized

常見類
? AtomicIntegerAtomicLong:整型原子操作。
? AtomicReference:對象引用原子操作。
? AtomicStampedReference:解決 ABA 問題(版本號控制)。

使用場景
適合 計數器累加器 等需要原子操作的場景。

public class Counter {private AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet();  // 原子自增}public int get() {return count.get();}
}

示例:AtomicReference 保證對象引用原子性

public class AtomicReferenceDemo {private AtomicReference<String> latestMessage = new AtomicReference<>("");public void updateMessage(String message) {latestMessage.set(message);  // 原子更新引用}public String getMessage() {return latestMessage.get();}
}

示例:解決 ABA 問題(AtomicStampedReference)

public class ABADemo {private AtomicStampedReference<Integer> atomicValue = new AtomicStampedReference<>(100, 0);  // 初始值100,版本號0public void update() {int[] stampHolder = new int[1];int currentValue = atomicValue.get(stampHolder);  // 獲取值和版本號int newValue = currentValue + 1;atomicValue.compareAndSet(currentValue, newValue, stampHolder[0], stampHolder[0] + 1);}
}
特性volatile原子類(如 AtomicInteger)
解決可見性問題??(強制主內存讀寫)??(內部使用 volatile 變量)
解決原子性問題?(如 i++ 仍不安全)??(封裝原子操作)
性能高(無鎖)高(CAS 無鎖)
適用場景狀態標志、開關控制計數器、累加器、復雜原子操作
ABA 問題無法解決可通過 AtomicStampedReference 解決

? volatile 是輕量級的可見性解決方案,不保證原子性
? 原子類通過 CAS 實現無鎖原子操作,同時解決可見性和原子性
? 兩者性能均優于鎖,但適用場景不同,不要混淆!

  1. volatile
    ? 變量被多個線程共享,但只有一個線程修改它。
    ? 需要立即可見性,但不涉及復合操作(如 i++)。
    ? 典型場景:狀態標志(boolean 開關)。

  2. 用原子類
    ? 變量被多個線程頻繁修改(如計數器)。
    ? 需要原子性操作(如 addAndGet()compareAndSet())。
    ? 典型場景:并發計數器、無鎖數據結構。

  3. synchronizedReentrantLock
    ? 需要同步多步操作(如先讀后寫)。
    ? 原子類和 volatile 無法滿足復雜邏輯時。


6. 讀寫鎖 ReentrantReadWriteLock

想象一個圖書館:
? 讀鎖:允許多個人同時讀書(共享資源)。
? 寫鎖:當有人要修改書的內容時,必須清場(獨占資源),其他人不能讀也不能寫。

核心規則

  1. 讀鎖之間不互斥:多個線程可以同時持有讀鎖。
  2. 寫鎖與其他鎖互斥:寫鎖生效時,其他線程不能獲取讀鎖或寫鎖。
  3. 寫鎖優先:如果寫鎖在等待,新來的讀鎖會被阻塞(防止“寫線程饑餓”)。

為什么用讀寫鎖?
讀多寫少 的場景下(如緩存系統、配置管理),用讀寫鎖比普通互斥鎖(如 synchronized)性能更高:
? 讀操作:允許多線程并發讀取。
? 寫操作:保證獨占修改,避免數據不一致。

場景:實現一個線程安全的緩存系統

public class Cache<K, V> {private final Map<K, V> cacheMap = new HashMap<>();private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();private final Lock readLock = rwLock.readLock();   // 讀鎖private final Lock writeLock = rwLock.writeLock(); // 寫鎖// 讀操作:允許多線程并發讀public V get(K key) {readLock.lock();try {return cacheMap.get(key);} finally {readLock.unlock();}}// 寫操作:獨占訪問public void put(K key, V value) {writeLock.lock();try {cacheMap.put(key, value);} finally {writeLock.unlock();}}// 復雜操作:先讀后寫(需要先釋放讀鎖,再獲取寫鎖)public void updateIfPresent(K key, V newValue) {readLock.lock();try {if (cacheMap.containsKey(key)) {// 釋放讀鎖,獲取寫鎖(注意:不能直接升級鎖!)readLock.unlock();writeLock.lock();try {cacheMap.put(key, newValue);} finally {writeLock.unlock();}// 重新獲取讀鎖(如果需要)readLock.lock();}} finally {readLock.unlock();}}
}

關鍵細節

  1. 避免鎖升級:先釋放讀鎖,再獲取寫鎖。
  2. 寫鎖優先:如果寫鎖在等待,后續讀鎖會被阻塞(可通過公平鎖緩解)。
  3. 鎖的釋放:必須用 try-finally 確保釋放,否則會導致死鎖。

在持有寫鎖時,可以獲取讀鎖,然后釋放寫鎖(保持數據可見性):

public void writeThenRead() {writeLock.lock();try {// 修改數據...readLock.lock();  // 鎖降級(允許)} finally {writeLock.unlock();}try {// 讀取數據...} finally {readLock.unlock();}
}

不能直接從讀鎖升級到寫鎖(會導致死鎖):

public void readThenWrite() {readLock.lock();try {// 如果發現需要修改數據...writeLock.lock();  // 錯誤!會阻塞,因為讀鎖未釋放,其他線程也無法釋放寫鎖} finally {readLock.unlock();}
}

線程同步方式的對比與選擇
方式原理適用場景性能
synchronized對象內置鎖簡單同步,少量競爭中等,自動釋放鎖
ReentrantLockAQS隊列鎖復雜控制(如超時、公平鎖)高,需手動釋放
volatile內存可見性單變量狀態標志極高,無鎖
原子類CAS指令計數器,單變量原子操作高,無鎖競爭
ReentrantReadWriteLock讀寫分離鎖讀多寫少場景讀高,寫中等
  1. 優先選擇高級工具:如java.util.concurrent包下的并發集合(ConcurrentHashMap, BlockingQueue)。
  2. 避免鎖粒度過大:盡量縮小同步范圍,減少競爭。
  3. 資源釋放:使用Lock時務必在finally中釋放鎖。
  4. 分工協作:讀寫分離時使用ReentrantReadWriteLock提升性能。
  5. 監測工具:利用jstackVisualVM排查死鎖和性能瓶頸。

五、Java線程安全集合詳解

Java提供了多種線程安全的集合類,適用于高并發場景。它們通過內部優化(如分段鎖、寫時復制)實現高效并發,避免開發者手動加鎖。以下是常見線程安全集合及其使用場景和示例:


1. ConcurrentHashMap(并發哈希表)

? 原理:將數據分為多個段(Segment,Java 8后改為Node數組+CAS),每個段獨立加鎖。允許多線程同時讀寫不同段的數據。
? 適用場景:高并發鍵值存儲(如緩存、計數器)。
? 示例

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();// 線程安全的插入(若key不存在)
map.putIfAbsent("apple", 1);// 原子累加操作
map.compute("apple", (k, v) -> v == null ? 1 : v + 1);// 遍歷(弱一致性迭代器,不拋ConcurrentModificationException)
map.forEach((k, v) -> System.out.println(k + ": " + v));

2. CopyOnWriteArrayList(寫時復制列表)

? 原理:寫操作時復制整個數組(加鎖保證原子性),讀操作無鎖。適合讀多寫少的場景。
? 適用場景:監聽器列表、配置信息列表。
? 示例

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("user1");// 讀操作無需加鎖
for (String user : list) {System.out.println(user);
}// 寫操作會復制新數組
list.add("user2"); // 原數組:[user1],新數組:[user1, user2]

3. BlockingQueue(阻塞隊列)

? 原理:當隊列空時阻塞消費者,隊列滿時阻塞生產者。內部通過ReentrantLockCondition實現。
? 常見實現
? ArrayBlockingQueue:有界隊列(數組實現)。
? LinkedBlockingQueue:可選有界或無界(鏈表實現)。
? PriorityBlockingQueue:優先級阻塞隊列。
? 適用場景:生產者-消費者模型。
? 示例

BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);// 生產者
new Thread(() -> {try {queue.put("task1"); // 隊列滿時阻塞} catch (InterruptedException e) {e.printStackTrace();}
}).start();// 消費者
new Thread(() -> {try {String task = queue.take(); // 隊列空時阻塞System.out.println("處理任務: " + task);} catch (InterruptedException e) {e.printStackTrace();}
}).start();

4. ConcurrentLinkedQueue(并發鏈表隊列)

? 原理:基于無鎖算法(CAS),實現非阻塞線程安全隊列。
? 適用場景:高并發非阻塞隊列(如任務分發)。
? 示例

ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();// 生產者
queue.offer(100); // 非阻塞添加// 消費者
Integer value = queue.poll(); // 非阻塞取出

5. ConcurrentSkipListMap(并發跳表映射)

? 原理:基于跳表(Skip List)數據結構,實現有序的并發Map。
? 適用場景:需要排序的高并發鍵值存儲(如排行榜)。
? 示例

ConcurrentSkipListMap<Integer, String> rank = new ConcurrentSkipListMap<>();
rank.put(90, "Alice");
rank.put(85, "Bob");// 按分數從高到低遍歷
rank.descendingMap().forEach((score, name) -> {System.out.println(name + ": " + score);
});

6. CopyOnWriteArraySet(寫時復制集合)

? 原理:基于CopyOnWriteArrayList實現,用數組存儲元素,寫操作時復制。
? 適用場景:讀多寫少的集合(如IP白名單)。
? 示例

CopyOnWriteArraySet<String> ips = new CopyOnWriteArraySet<>();
ips.add("192.168.1.1");// 檢查IP是否存在(無需加鎖)
if (ips.contains("192.168.1.1")) {System.out.println("IP允許訪問");
}

7. Collections.synchronizedXXX(同步包裝類)

? 原理:通過包裝普通集合,對所有方法加synchronized鎖。
? 適用場景:低并發環境(性能低于專用并發集合)。
? 示例

List<String> syncList = Collections.synchronizedList(new ArrayList<>());// 遍歷時需手動加鎖
synchronized (syncList) {for (String item : syncList) {System.out.println(item);}
}

線程安全集合對比表
集合名稱原理適用場景性能特點
ConcurrentHashMap分段鎖/CAS高并發鍵值存儲高吞吐量,低延遲
CopyOnWriteArrayList寫時復制讀多寫少的列表寫操作慢,讀操作快
BlockingQueue鎖+條件隊列生產者-消費者模型阻塞操作,適用于任務調度
ConcurrentLinkedQueue無鎖(CAS)高并發非阻塞隊列高并發,無鎖
ConcurrentSkipListMap跳表有序并發鍵值存儲查詢和插入O(log n)
CopyOnWriteArraySet基于CopyOnWriteArrayList讀多寫少的集合CopyOnWriteArrayList
  1. 鍵值存儲
    ? 高并發寫入:ConcurrentHashMap
    ? 需要排序:ConcurrentSkipListMap

  2. 列表/集合
    ? 讀多寫少:CopyOnWriteArrayList/CopyOnWriteArraySet
    ? 寫操作頻繁:使用ConcurrentHashMap模擬(如Collections.newSetFromMap

  3. 隊列
    ? 阻塞隊列:ArrayBlockingQueue/LinkedBlockingQueue
    ? 非阻塞隊列:ConcurrentLinkedQueue

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

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

相關文章

PCL 計算點云至平面距離(SIMD加速)

文章目錄 一、簡介二、實現代碼三、實現效果一、簡介 SIMD 是一種并行計算模型,其中“單指令”表示處理器在同一時刻執行相同的指令,而“多數據”則表示同一條指令操作多個數據元素(如數組中的多個元素或矩陣中的多個元素)。與傳統的串行計算不同,SIMD 能夠同時處理多個數…

Ubuntu 22.04 完美安裝 ABAQUS 教程:從零到上手,解決兼容問題

教程概述與安裝準備 本教程詳細介紹了在 Ubuntu 22.04 系統上安裝 ABAQUS 2023 及 ifort 2021 的步驟,并實現用戶子程序的鏈接。教程同樣適用于 ABAQUS 2021(需相應調整文件名和路徑)以及 Ubuntu 18.04 至 22.04 系統,盡管未在所有版本上測試。需要注意的是,Intel 的 One…

Spark-TTS(Text-to-Speech):基于大語言模型的語音合成革新者!!!

Spark-TTS&#xff1a;基于大語言模型的語音合成革新者 &#x1f680; &#xff08;全稱解析 核心特性 行業影響全解讀&#xff09; 一、概念定義與技術定位 1. 英文全稱 Spark-TTS: An Efficient LLM-Based Text-to-Speech Model ? 關鍵詞解析&#xff1a; ? LLM-Based…

2025年十六屆藍橋杯Python B組原題及代碼解析

相關試題可以在洛谷上測試用例&#xff1a; 2025 十六屆 藍橋杯 Python B組 試題 A&#xff1a;攻擊次數 答案&#xff1a;103 print(103)代碼&#xff1a; # 初始化敵人的血量 x 2025# 初始化回合數 turn 0# 模擬攻擊過程 while x > 0:# 回合數加一turn 1# 第一個英…

Spring Boot項目中結合MyBatis實現MySQL的自動主從切換

原理解析 1. MySQL主從復制&#xff08;Master-Slave Replication&#xff09; 工作原理&#xff1a;MySQL主從復制通過二進制日志&#xff08;binary log&#xff09;來同步數據。主服務器記錄所有更改操作到二進制日志中&#xff0c;從服務器讀取這些日志并執行相應的SQL語…

【經驗記錄貼】使用配置文件提高項目的可維護性

mark一下。 整體修改前后如下&#xff1a; 課題&#xff1a; 在項目中有一個支持的文件類型的FILE_TYPE的定義&#xff0c; 這個是寫死在主程序中&#xff0c;每次增加可以支持的文件類型的時候&#xff0c;都需要去修改主程序中這個FILGE_TYPE的定義。 主程序修改其實不太花時…

用DeepSeek AI高效制作專業PPT

在當今職場中,制作精美而有力的PPT是展示想法、匯報工作和贏得機會的關鍵技能。然而,許多人花費過多時間在格式調整和內容組織上,而非專注于核心信息的傳達。DeepSeek AI作為新一代智能助手,能夠幫助您將PPT制作效率提升300%,同時顯著提高專業度。本文將詳細介紹如何利用D…

【AI學習從零至壹】語?模型及詞向量相關知識

語?模型及詞向量相關知識 ?然語?處理簡介?然語?理解&#xff08;NLU&#xff09;?然語??成&#xff08;NLG&#xff09;發展趨勢信息檢索技術布爾檢索與詞袋模型基于相關性的檢索 / TF-IDF舉例&#xff1a; 語?模型 / Language Model神經?絡語?模型Word2Vec訓練?法…

15.【.NET 8 實戰--孢子記賬--從單體到微服務--轉向微服務】--單體轉微服務--如何拆分單體

單體應用&#xff08;Monolithic Application&#xff09;是指將所有功能模塊集中在一個代碼庫中構建的應用程序。它通常是一個完整的、不可分割的整體&#xff0c;所有模塊共享相同的運行環境和數據庫。這種架構開發初期較為簡單&#xff0c;部署也較為方便&#xff0c;但隨著…

在ARM架構Mac上部署Python 3.12與Conda環境的全鏈路指南!!!

在ARM架構Mac上部署Python 3.12與Conda環境的全鏈路指南 &#x1f680; &#xff08;M1/M2芯片實測&#xff5c;含性能調優避坑手冊&#xff09; &#x1f31f; 核心價值點 ? 原生ARM支持&#xff1a;突破Rosetta轉譯的性能損耗 ? 環境隔離&#xff1a;Conda虛擬環境管理多…

yml文件上傳并映射到實體類

文章目錄 功能背景功能需要前端開發組件選用組件嵌套和參數綁定上傳邏輯示例 后端開發接收邏輯解析邏輯省流純手動實現&#xff08;不建議&#xff09; 功能背景 開發一個配置文件解析功能&#xff0c;需要兼容老版本的配置文件。 功能需要 前端&#xff1a;兩個配置文件分別…

ElasticSearch中常用的數據類型

一、映射 Elasticsearch中通過映射來指定字段的數據類型&#xff0c;映射方式有2種&#xff0c;靜態映射和動態映射。 1.動態映射 使用動態映射時&#xff0c;無須指定字段的數據類型&#xff0c;Elasticshearch會自動根據字段內容來判斷映射到哪個數據類型。 比如&#xff…

【神經網絡結構的組成】深入理解 轉置卷積與轉置卷積核

&#x1f308; 個人主頁&#xff1a;十二月的貓-CSDN博客 &#x1f525; 系列專欄&#xff1a; &#x1f3c0;《深度學習理論直覺三十講》_十二月的貓的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻擋不了春天的腳步&#xff0c;十二點的黑夜遮蔽不住黎明的曙光 …

CSS高度坍塌?如何解決?

一、什么是高度坍塌&#xff1f; 高度坍塌&#xff08;Collapsing Margins&#xff09;是指當父元素沒有設置邊框&#xff08;border&#xff09;、內邊距&#xff08;padding&#xff09;、內容&#xff08;content&#xff09;或清除浮動時&#xff0c;其子元素的 margin 會…

Web前端開發——格式化文本與段落(上)

一、學習目標 網頁內容的排版包括文本格式化、段落格式化和整個頁面的格式化&#xff0c;這是設計個網頁的基礎。文本格式化標記分為字體標記、文字修飾標記。字體標記和文字修飾標記包括對于字體樣式的一些特殊修改。段落格式化標記分為段落標記、換行記、水平分隔線標記等。…

關于PHP開源CMS系統ModStart的詳細介紹及使用指南

關于PHP開源CMS系統ModStart的詳細介紹及使用指南&#xff1a; &#x1f50d; ModStart是什么&#xff1f; 基于Laravel框架開發的模塊化CMS系統采用Apache 2.0 開源協議&#xff0c;完全免費可商用特別適合需要快速搭建企業級網站/管理系統的開發者 &#x1f680; 核心優勢…

TCP標志位抓包

說明 TCP協議的Header信息&#xff0c;URG、ACK、PSH、RST、SYN、FIN這6個字段在14字節的位置&#xff0c;對應的是tcp[13]&#xff0c;因為字節數是從[0]開始數的&#xff0c;14字節對應的就是tcp[13]&#xff0c;因此在抓這幾個標志位的數據包時就要明確范圍在tcp[13] 示例1…

RK3588S開發板將SPI1接口改成GPIO

參考官方教程&#xff1a;ROC-RK3588S-PC 一.基本知識&#xff1a; 1.GPIO引腳計算&#xff1a; ROC-RK3588S-PC 有 5 組 GPIO bank&#xff1a;GPIO0~GPIO4&#xff0c;每組又以 A0~A7, B0~B7, C0~C7, D0~D7 作為編號區分&#xff0c;常用以下公式計算引腳&#xff1a;GPIO…

Java 設計模式:適配器模式詳解

Java 設計模式&#xff1a;適配器模式詳解 適配器模式&#xff08;Adapter Pattern&#xff09;是一種結構型設計模式&#xff0c;它通過將一個類的接口轉換為客戶端期望的另一個接口&#xff0c;使原本不兼容的類能夠協同工作。適配器模式就像現實生活中的電源適配器&#xf…

python manimgl數學動畫演示_微積分_線性代數原理_ubuntu安裝問題[已解決]

1.背景 最近調研python opencv, cuda加速矩陣/向量運算, 對于矩陣的線性變換, 秩, 轉秩, 行列式變化等概概念模糊不清. 大概課本依舊是天書, 于是上B站搜索線性代數, 看到 3Blue1Brown 線性變換本質 視頻, 點擊觀看. 驚為天人 --> 豁然開朗 --> 突然頓悟 --> 開心不已…