Java并發編程高頻面試題

一、基礎概念

1. 并行與并發的區別?

  • 并行:多個任務在多個CPU核心上同時執行(物理上同時)。
  • 并發:多個任務在單CPU核心上交替執行(邏輯上同時)。
  • 類比:并行是多個窗口同時服務,并發是一個窗口輪流服務。

2. 線程的創建方式?

  • 繼承Thread:重寫run()方法,通過start()啟動。
  • 實現Runnable接口:更靈活,避免單繼承限制。
  • 實現Callable接口:支持返回值和異常處理,配合FutureTask使用。

3. 線程的狀態?

狀態說明
NEW線程被創建但未啟動
RUNNABLE線程正在執行或等待CPU資源
BLOCKED線程等待鎖(進入同步代碼塊)
WAITING線程調用wait()/join()后等待喚醒
TIMED_WAITING超時等待(如sleep(long)
TERMINATED線程執行完畢或異常終止

4. sleep()wait()的區別?

特性sleep()wait()
所屬類ThreadObject
鎖行為不釋放鎖釋放鎖
喚醒方式超時自動喚醒需其他線程調用notify()喚醒
使用場景線程休眠線程間通信

5. 進程與線程的區別?

  • 進程:資源分配的最小單位(如內存、文件句柄)。
  • 線程:調度的最小單位,共享進程資源(如堆、方法區),但有獨立棧和寄存器。
  • 協程:比線程更輕量級(如Kotlin的Coroutine)。

6.為什么用start()而非直接調用run()?

  • start()會創建新線程并執行run(),而直接調用run()僅在當前線程執行,無并發效果。

二、ThreadLocal

7. ThreadLocal的作用?

  • 線程隔離:為每個線程提供獨立變量副本,避免共享數據沖突。
  • 典型場景:用戶會話管理、數據庫連接上下文傳遞。

8. ThreadLocal的實現原理?

  • 線程私有Map:每個線程維護一個ThreadLocal.ThreadLocalMap,鍵為ThreadLocal對象,值為線程變量。
  • 弱引用:鍵使用弱引用,防止內存泄漏。

9. ThreadLocal內存泄漏問題?

  • 原因:線程未及時調用remove(),導致Entryvalue強引用無法被回收。
  • 解決:使用try-finally確保調用remove()

三、Java內存模型(JMM)

9.JMM的核心是什么?

  • 定義線程間共享變量的訪問規則,解決可見性、有序性、原子性問題。
  • 主內存:共享變量存儲區。
  • 本地內存:線程私有的共享變量副本(抽象概念,對應CPU緩存等)。

10. JMM的三大特性?

  • 原子性:操作不可分割(如synchronized保證代碼塊原子性)。
  • 可見性:一個線程修改的值對其他線程立即可見(volatilesynchronized)。
  • 有序性:禁止指令重排序(volatile通過內存屏障實現)。

11. volatile的作用?

  • 可見性:強制將修改刷新到主內存,禁止緩存。
  • 有序性:通過內存屏障禁止指令重排序。

12. volatile的作用及實現原理?

  • 作用:保證可見性和禁止指令重排。
  • 原理:
    • 寫操作后插入Store-Barrier,強制刷新主內存。
    • 讀操作前插入Load-Barrier,強制從主內存讀取。

四、鎖機制

13. synchronized的使用方式?

  • 修飾方法:鎖對象實例(非靜態方法)或類(靜態方法)。
  • 修飾代碼塊:指定鎖對象,更細粒度控制。

14. synchronized的實現原理?

  • Monitor對象:每個Java對象關聯一個監視器,線程通過獲取Monitor實現互斥。
  • 鎖升級:偏向鎖 → 輕量級鎖 → 重量級鎖(基于CAS和自旋優化)。

15. synchronized與ReentrantLock的區別?

特性synchronizedReentrantLock
可重入自動支持需手動釋放(unlock()
公平性非公平支持公平鎖(通過構造函數)
鎖獲取阻塞等待支持tryLock()非阻塞獲取
條件變量wait()/notify()支持Condition多條件變量

15. CAS的原理及問題?

  • 原理:Compare-And-Swap,通過原子指令實現無鎖操作。
  • 問題
    • ABA問題:通過版本號(如AtomicStampedReference)解決。
    • 循環開銷:長時間自旋消耗CPU。

五、并發工具類

16. CountDownLatch與CyclicBarrier的區別?

  • CountDownLatch:計數器遞減至0時釋放所有等待線程(一次性)。
  • CyclicBarrier:所有線程到達屏障后繼續執行(可重用)。

17. Semaphore的作用?

  • 控制并發量:允許指定數量的線程同時訪問資源。
  • 應用場景:限流、資源池管理。

六、線程池

18. 線程池的工作流程?

  1. 任務提交到線程池。
  2. 核心線程處理任務,空閑則創建新線程(未達最大線程數)。
  3. 任務隊列已滿且線程數達最大值時,觸發拒絕策略。

提交任務 → 核心線程執行 → 隊列緩沖 → 最大線程處理 → 拒絕策略。

19. 線程池參數配置?

  • corePoolSize:核心線程數。
  • maximumPoolSize:最大線程數。
  • keepAliveTime:空閑線程存活時間。
  • workQueue:阻塞隊列(如LinkedBlockingQueue)。
  • handler:拒絕策略(如AbortPolicy)。

20. 線程池的拒絕策略?

  • AbortPolicy:拋異常(默認)。
  • CallerRunsPolicy:任務回退到調用線程執行。
  • DiscardPolicy:靜默丟棄。
  • DiscardOldestPolicy:丟棄隊列中最老的任務。

七、高級主題

21. 死鎖的條件及避免?

  • 條件:互斥、持有并等待、不可搶占、循環等待。
  • 避免
    • 按順序加鎖。
    • 設置超時時間。
    • 使用ReentrantLocktryLock()

22. ConcurrentHashMap的線程安全機制?

  • 分段鎖(JDK7):將數據分段,鎖粒度細化。
  • CAS+synchronized(JDK8):數組+鏈表/紅黑樹結構,CAS保證原子性,synchronized保證同步。

23.CAS的問題及解決?

  • 問題:ABA問題、循環開銷大。
  • 解決:AtomicStampedReference解決ABA,結合volatile減少循環。

八、代碼實戰

24. 手寫雙重校驗單例模式?

public class Singleton {private static volatile Singleton instance; // 禁止指令重排private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次檢查synchronized (Singleton.class) { // 加鎖if (instance == null) { // 第二次檢查instance = new Singleton(); // 初始化對象}}}return instance;}
}

volatile的必要性

  • 防止instance = new Singleton()的指令重排(先分配內存,再初始化對象,最后賦值引用)。
  • 若未使用volatile,其他線程可能在初始化完成前拿到未完全構造的對象。

25.線程的創建方式對比

// 繼承Thread類
public class ThreadDemo extends Thread {@Overridepublic void run() {System.out.println("Thread running");}
}// 實現Runnable接口
public class RunnableDemo implements Runnable {@Overridepublic void run() {System.out.println("Runnable running");}
}// 實現Callable接口
public class CallableDemo implements Callable<String> {@Overridepublic String call() throws Exception {return "Callable result";}
}// 使用示例
public static void main(String[] args) throws Exception {// Threadnew ThreadDemo().start();// Runnablenew Thread(new RunnableDemo()).start();// Callable + FutureTaskFutureTask<String> futureTask = new FutureTask<>(new CallableDemo());new Thread(futureTask).start();System.out.println("Result: " + futureTask.get());
}

原理對比:

  • Thread類本身實現了Runnable接口,通過繼承方式耦合度較高。
  • Runnable和Callable將任務與線程解耦,支持更靈活的擴展。
  • Callable通過FutureTask包裝后,可通過get()方法獲取異步結果。

26.ThreadLocal內存泄漏

public class ThreadLocalDemo {private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {threadLocal.set("value");// 未調用threadLocal.remove(),可能導致內存泄漏}
}

原理分析:

  • ThreadLocalMap的Entry以ThreadLocal為鍵(弱引用),若未手動remove(),當ThreadLocal對象被回收后,value仍被強引用在Entry中。
  • 解決方案
try {threadLocal.set("value");// 業務邏輯
} finally {threadLocal.remove(); // 在finally中確保清理
}

27.volatile的內存屏障

public class VolatileDemo {private volatile int x = 0;public void write() {x = 1; // 寫操作后插入Store-Barrier}public void read() {int y = x; // 讀操作前插入Load-Barrier}
}

內存屏障原理

  • Store-Barrier:確保屏障前的寫操作全部刷新到主內存。
  • Load-Barrier:確保屏障后的讀操作從主內存獲取最新值。
  • 禁止指令重排:通過內存屏障阻止編譯器和CPU對volatile變量操作的重排序。

28.synchronized vs ReentrantLock

// synchronized示例
public class SynchronizedDemo {public synchronized void method() {// 同步代碼}
}// ReentrantLock示例
public class ReentrantLockDemo {private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {// 同步代碼} finally {lock.unlock();}}
}

29.CountDownLatch vs CyclicBarrier

// CountDownLatch示例
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(2);new Thread(() -> {System.out.println("Task1 done");latch.countDown();}).start();new Thread(() -> {System.out.println("Task2 done");latch.countDown();}).start();latch.await(); // 等待兩個任務完成System.out.println("All tasks done");}
}// CyclicBarrier示例
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(2, () -> {System.out.println("Barrier reached");});new Thread(() -> {try {System.out.println("Task1 ready");barrier.await();System.out.println("Task1 continue");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();new Thread(() -> {try {System.out.println("Task2 ready");barrier.await();System.out.println("Task2 continue");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();}
}

核心區別

  • CountDownLatch:計數器遞減到0后不可重置,用于“等待多個任務完成”。
  • CyclicBarrier:計數器達到閾值后重置,可循環使用,用于“多個線程同步執行”。

30.線程池工作流程

ExecutorService executor = new ThreadPoolExecutor(2, // corePoolSize4, // maximumPoolSize30, // keepAliveTimeTimeUnit.SECONDS,new ArrayBlockingQueue<>(10), // workQueueExecutors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy() // 拒絕策略
);

工作流程

  1. 提交任務 → 核心線程執行(未達corePoolSize時創建新線程)。
  2. 核心線程滿 → 任務存入隊列(如ArrayBlockingQueue)。
  3. 隊列滿 → 非核心線程執行(不超過maximumPoolSize)。
  4. 所有線程忙且隊列滿 → 觸發拒絕策略(如AbortPolicy拋異常)。

31.CAS的ABA問題

AtomicInteger atomicInt = new AtomicInteger(100);
// 線程A:
int oldValue = atomicInt.get();
// 假設線程B將值改為101,再改回100
atomicInt.compareAndSet(oldValue, 200); // CAS成功,但值已被篡改

解決方案

AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(100, 0);
// 線程A:
int[] stampHolder = new int[1];
int oldValue = stampedRef.get(stampHolder);
int oldStamp = stampHolder[0];
// 線程B修改值并增加版本號
stampedRef.compareAndSet(oldValue, 101, oldStamp, oldStamp + 1);
// 線程A再次嘗試CAS:
stampedRef.compareAndSet(oldValue, 200, oldStamp, oldStamp + 1); // 失敗(版本號不匹配)

總結:以上題目覆蓋Java并發編程核心知識點,建議重點掌握線程安全實現、鎖優化、JMM原理、線程池調優等模塊。面試時需結合源碼和實際場景說明設計原理,體現對底層機制的理解。

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

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

相關文章

LiT and Lean: Distilling Listwise Rerankers intoEncoder-Decoder Models

文章&#xff1a;ECIR 2025會議 一、動機 背景&#xff1a;利用LLMs強大的能力&#xff0c;將一個查詢&#xff08;query&#xff09;和一組候選段落作為輸入&#xff0c;整體考慮這些段落的相關性&#xff0c;并對它們進行排序。 先前的研究基礎上進行擴展 [14,15]&#xff0c…

Python高級爬蟲之JS逆向+安卓逆向1.2節: 變量與對象

目錄 引言&#xff1a; 1.2.1 Python中的變量 1.2.2 變量的命名與可讀性 1.2.3 Python中的對象 1.2.4 跟大神學高級爬蟲安卓逆向 引言&#xff1a; 大神薯條老師的高級爬蟲安卓逆向教程&#xff1a; 這套爬蟲教程會系統講解爬蟲的初級&#xff0c;中級&#xff0c;高級知…

可發1區的超級創新思路(python 實現):一種輕量化的動態稀疏門控網絡

首先聲明,該模型為原創!原創!原創!且該思路還未有成果發表,感興趣的小伙伴可以借鑒! 一、應用領域 視頻異常檢測、生成視頻檢測。 二、模型解析 該模型由1.關鍵幀動態選擇機制、2.關鍵幀動態選擇機制以及3.關鍵幀動態選擇機制三大核心組件構成,形成端到端的視頻異常…

使用NVM下載Node.js管理多版本

提示&#xff1a;我解決這個bug跟別人思路可能不太一樣&#xff0c;因為我是之前好用&#xff0c;換個項目就不好使了&#xff0c;倦了 文章目錄 前言項目場景一項目場景二解決方案&#xff1a;下載 nvm安裝 nvm重新下載所需Node 版本nvm常用命令 項目結構說明 前言 提示&…

MySQL數據庫經典面試題解析

1. MySQL 索引使用有哪些注意事項呢? 可以從三個維度回答這個問題:索引哪些情況會失效,索引不適合哪些場景,索引規則 索引哪些情況會失效 查詢條件包含or,可能導致索引失效如何字段類型是字符串,where時一定用引號括起來,否則索引失效like通配符可能導致索引失效。聯合…

C#結合SQLite數據庫使用方法

一、關于SQLite SQLite 是一個輕量級的嵌入式關系型數據庫管理系統&#xff08;RDBMS&#xff09;。與傳統的數據庫管理系統&#xff08;如 MySQL、PostgreSQL 或 SQL Server&#xff09;不同&#xff0c;SQLite 并不需要運行單獨的服務器進程&#xff0c;它的數據庫存儲在一個…

深入解析 MySQL 中的日期時間函數:DATE_FORMAT 與時間查詢優化

深入解析 MySQL 中的日期時間函數&#xff1a;DATE_FORMAT 與時間查詢優化 在數據庫管理和應用開發中&#xff0c;日期和時間的處理是不可或缺的一部分。MySQL 提供了多種日期和時間函數來滿足不同的需求&#xff0c;其中DATE_FORMAT函數以其強大的日期格式化能力&#xff0c;…

如何深刻理解Reactor和Proactor

前言&#xff1a; 網絡框架的設計離不開 I/O 線程模型&#xff0c;線程模型的優劣直接決定了系統的吞吐量、可擴展性、安全性等。目前主流的網絡框架&#xff0c;在網絡 IO 處理層面幾乎都采用了I/O 多路復用方案(又以epoll為主)&#xff0c;這是服務端應對高并發的性能利器。 …

筆試專題(七)

文章目錄 乒乓球筐&#xff08;哈希&#xff09;題解代碼 組隊競賽題解代碼 刪除相鄰數字的最大分數&#xff08;線性dp&#xff09;題解代碼 乒乓球筐&#xff08;哈希&#xff09; 題目鏈接 題解 1. 兩個哈希表 先統計第一個字符串中的字符個數&#xff0c;再統計第二個字…

清晰易懂的 Flutter 卸載和清理教程

以下是為 Flutter 徹底卸載與清理教程&#xff0c;覆蓋 Windows、macOS、Linux 系統&#xff0c;步驟清晰無殘留&#xff0c;確保完全刪除 Flutter SDK、依賴工具及 IDE 配置。 一、通用步驟&#xff1a;確認 Flutter 安裝方式 Flutter 通常通過以下方式安裝&#xff1a; 手動…

關于反卷積

&#x1f9e0; 什么是反卷積&#xff1f; 反卷積&#xff08;Deconvolution&#xff09;&#xff0c;通常也稱為轉置卷積&#xff08;Transpose Convolution&#xff09;&#xff0c;是一種用于擴展輸入特征圖的操作&#xff0c;通常用于生成圖像或上采樣任務中。與標準卷積操…

【機器學習】ROC 曲線與 PR 曲線

目錄 一、混淆矩陣&#xff1a;分類評估的基礎 二. ROC 曲線 (Receiver Operating Characteristic Curve) 三. PR 曲線 (Precision-Recall Curve) 3.1 核心思想 4. 何時使用 ROC 曲線和 PR 曲線&#xff1f; 實驗結果 6. 總結 在機器學習的分類任務中&#xff0c;我們訓…

Python高階函數-map

map() 是 Python 內置的一個高階函數&#xff0c;它接收一個函數和一個可迭代對象作為參數&#xff0c;將函數依次作用在可迭代對象的每個元素上&#xff0c;并返回一個迭代器&#xff08;Python 3.x 中&#xff09;。 基本語法 map(function, iterable, ...)function: 應用于…

上海餐飲市場數據分析與可視化

上海作為中國的經濟中心和國際化大都市,其餐飲市場具有高度的多樣性和競爭性。隨著消費者需求的不斷變化,餐飲行業的從業者和投資者需要深入了解市場現狀和趨勢,以便制定更有效的商業策略。本文將通過數據分析和可視化技術,深入探討上海餐飲市場的現狀和趨勢,為餐飲從業者…

MySQL基礎 [五] - 表的增刪查改

目錄 Create&#xff08;insert&#xff09; Retrieve&#xff08;select&#xff09; where條件 ?編輯 NULL的查詢 結果排序(order by) 篩選分頁結果 (limit) Update Delete 刪除表 截斷表&#xff08;truncate&#xff09; 插入查詢結果&#xff08;insertselect&…

SQL:Primary Key(主鍵)和Foreign Key(外鍵)

目錄 1. Key&#xff08;鍵&#xff09; 2. Index&#xff08;索引&#xff09; 3.Key和Index的區別 4. Primary Key&#xff08;主鍵&#xff09; 5. Foreign Key&#xff08;外鍵&#xff09; 6.主鍵和外鍵的關系 溫馨提示&#xff1a; 閃電按鈕不同的執行功能 首先&…

2025年- H1-Lc109-160. 相交列表--java版

1.題目描述 2.思路 “雙指針切換鏈表頭” 思路一&#xff1a;雙指針路徑對齊 while (pA ! pB) { pA (pA null) ? headB : pA.next; pB (pB null) ? headA : pB.next; } 讓兩個指針走相同的總路徑長度&#xff01; 設&#xff1a; 鏈表 A 獨有部分長度是 lenA 鏈表 B …

PyTorch 深度學習 || 6. Transformer | Ch6.3 Transformer 簡單案例

1. 簡單案例 這個代碼是一個簡單的 Transformer 模型的實現,這個例子展示了一個基本的序列到序列(seq2seq)任務,比如將一個數字序列轉換為另一個數字序列。可以用于學習和理解 Transformer 的基本結構和工作原理。 import torch import torch.nn as nn import math# 位置…

基礎算法篇(4)(藍橋杯常考點)—數據結構(進階)

前言 這期將會講到基礎算法篇里面的數據結構&#xff08;進階&#xff09;&#xff0c;主要包括單調棧&#xff0c;單調隊列&#xff0c;并查集&#xff0c;擴展域并查集&#xff0c;帶權并查集&#xff0c;字符串哈希&#xff0c;Trie樹。 數據結構(進階&#xff09;正文 單…

【AI學習】初步了解Gradio

Gradio 是一個開源的 Python 庫&#xff0c;專注于快速構建交互式 Web 界面&#xff0c;特別適用于機器學習模型、數據科學項目或任意 Python 函數的演示與部署。它通過極簡的代碼實現前后端一體化&#xff0c;無需前端開發經驗即可創建功能豐富的應用。以下是 Gradio 的核心特…