面試中的線程題

原文鏈接:線程題大全

Java 并發庫同步輔助類

CountDownLatch

工作機制:初始化一個計數器,此計數器的值表示需要等待的事件數量。

提供了兩個主要方法:

  • await():當一個線程調用此方法時,它將阻塞,直到計數器的值為 0
  • countDown():用于減少計數器的值。通常表示一個事件已經發生了(如任務完成),當計數器的值減到 0 時,所有調用 await()并阻塞的線程將被喚醒并繼續執行

重要特性:

  • 不可重置:一旦計數器的值為 0,就不能再被重置回初識值或其他任何值
  • 一次性的:計數值到達 0 后,所有在 await()方法上等待的線程將被釋放,而后續的 await()方法調用將立即通過,不會進行阻塞
  • 多用途同步工具:能被用于多種目的,等待服務的初始化、一組任務或某個事件的發生

示例:在兩個工作線程結束后再調用主線程

CountDownLatch latch = new CountDownLatch(2); // 設定計數器初始值為2// 創建第一個線程,完成某項任務后調用countDown方法
new Thread(() -> {System.out.println("線程1執行...");latch.countDown();System.out.println("線程1完成操作,計數器減一");
}).start();// 創建第二個線程,也是完成某項任務后調用countDown方法
new Thread(() -> {System.out.println("線程2執行...");latch.countDown();System.out.println("線程2完成操作,計數器減一");
}).start();try {// 調用await方法的線程會被阻塞,直到計數器的值變為0latch.await();System.out.println("兩個線程的操作均已完成,主線程繼續執行");
} catch (InterruptedException e) {e.printStackTrace();
}
CyclicBarrier

工作機制:允許一組線程相互等待到達一個共同屏障點

重要特性:

  • 屏障:允許提供一個 Runnable 任務,在所有線程都到達屏障,線程釋放前執行該任務。通常用于合并最終結果或者進行某種必須等到所有線程都到達屏障點后才能執行的操作
  • 等待線程數:在創建 CyclicBarrier 時,需要指定等待的線程數量。當指定數量的線程都調用 await()方法,表示它們都到達了屏障點,隨后這些線程都將被釋放
  • 超時與中斷:線程在調用 await()方法時可以選擇設置超時時間,超時或者被中斷都將導致線程提前釋放,并拋出相應異常
  • 重置:釋放等待線程后重置計數器。

示例:當四個線程都達到屏障后,打印一句話,然后每個線程繼續執行它們的任務

public class CyclicBarrierExample {// 創建一個新的CyclicBarrier,當四個參與者到達時執行屏障操作private CyclicBarrier barrier = new CyclicBarrier(4, () -> System.out.println("所有線程到達屏障點,屏障操作執行!"));public void startTask(String name) {new Thread(() -> {System.out.println(name + "開始執行任務...");// 模擬任務耗時try {Thread.sleep((int)(Math.random() * 1000));} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name + "到達屏障點,等待其他線程...");try {// 調用await方法等待其他線程都到達屏障點barrier.await();} catch (Exception e) {e.printStackTrace();}System.out.println(name + "繼續執行后續操作");}).start();}public static void main(String[] args) {CyclicBarrierExample example = new CyclicBarrierExample();example.startTask("線程A");example.startTask("線程B");example.startTask("線程C");example.startTask("線程D"); // 當所有四個線程達到屏障點,將一起釋放,然后執行屏障操作}
}

線程交叉打印模版

public class CrossPrinter {private int state;private final int printCount;public CrossPrinter(int printCount) {// state用來確定下次打印this.state = 0;// 打印次數this.printCount = printCount;}public void printLetter(String Letter, int crossState ,int curState) {for (int i = 0; i < printCount; i++) {synchronized (this) {while (state % crossState != curState) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + ":" + Letter);state++;notifyAll();}}}public static void main(String[] args) {CrossPrinter crossPrinter = new CrossPrinter(5);// Thread A打印"A"new Thread(() -> crossPrinter.printLetter("A", 2,0), "Thread A").start();// Thread B打印"B"new Thread(() -> crossPrinter.printLetter("B", 2,1), "Thread B").start();}}

上述完成了兩線程交叉打印"A"、“B”,具體說明下

  • printCount:控制交叉打印次數
  • state:全局變量,指明線程已經執行多少次了
  • crossState:指明有多少個線程進行交叉
  • curState:指明當前線程
  • Letter:當前線程打印內容

可用于:

  • 多線程交叉打印 A、B、C…
  • 兩線程交叉打印奇偶數
三線程交叉打印 A、B、C

模版中是兩線程交叉打印 A、B,只需要做簡單替換就能實現三線程交叉打印 A、B、C

crossState:3

新增線程 C 如下

// Thread A打印"A"
new Thread(() -> crossPrinter.printLetter("A", 3,0), "Thread A").start();// Thread B打印"B"
new Thread(() -> crossPrinter.printLetter("B", 3,1), "Thread B").start();// Thread C打印"C"
new Thread(() -> crossPrinter.printLetter("C", 3,2), "Thread C").start();
兩線程交叉打印奇偶數

比如要求打印到兩線程交叉打印到 10

state 控制線程進行輪次,此時可以換為 while 條件,用來控制跳出循環

crossState:2,表示兩線程

完整代碼如下:

public class CrossPrinter {private int state;private final int printCount;public CrossPrinter(int printCount) {// state用來確定下次打印this.state = 0;// printCount表示打印次數this.printCount = printCount;}public void printNumber(int crossState ,int curState) {while (state < printCount) {synchronized (this) {while (state % crossState != curState) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + ":" + state);state++;notifyAll();}}}public static void main(String[] args) {CrossPrinter crossPrinter = new CrossPrinter(10);// Thread A打印偶數new Thread(() -> crossPrinter.printNumber(2,0), "Thread A").start();// Thread B打印奇數new Thread(() -> crossPrinter.printNumber(2,1), "Thread B").start();}}
三線程交叉打印斐波那契數列

新增 oneNum、twoNum 來記錄前兩個數

完整代碼如下

public class CrossPrinter {private int state;private int oneNum;private int twoNum;private final int printCount;public CrossPrinterThree(int printCount) {this.state = 3;this.oneNum = 1;this.twoNum = 1;this.printCount = printCount;}public static void main(String[] args) {CrossPrinterThree crossPrinterThree = new CrossPrinter(10);// 三線程交叉打印斐波那契數列new Thread(() -> crossPrinterThree.printNum(3, 0), "Thread-A").start();new Thread(() -> crossPrinterThree.printNum(3, 1), "Thread-B").start();new Thread(() -> crossPrinterThree.printNum(3, 2), "Thread-C").start();}private void printNum(int crossState, int curState) {while (state < printCount) {synchronized (this) {while (state % crossState != curState) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}int curNum = oneNum + twoNum;System._out_.println(Thread._currentThread_().getName() + ":" + curNum);// 更新前兩個數oneNum = twoNum;twoNum = curNum;state++;notifyAll();}}}}

多線程任務執行 A -> B, A -> C

實現方案:CountDownLatch

  • 為線程 B、C 分別設置 CountDownLatch 鎖,當線程 A 執行后,喚醒線程 B、C 的 CountDownLatch 鎖
public class MultiThreadTaskExecution {// 使用兩個初始計數為1的CountDownLatch來實現一對多的通知機制private CountDownLatch latchToB = new CountDownLatch(1);private CountDownLatch latchToC = new CountDownLatch(1);public void taskA() {System.out.println("任務A執行中...");try {Thread.sleep(100); // 模擬任務A執行時間} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任務A執行完畢,通知任務B、C開始執行...");latchToB.countDown();latchToC.countDown();}public void taskB() {try {latchToB.await();System.out.println("任務B執行中...");Thread.sleep(100); // 模擬任務B執行時間System.out.println("任務B執行完畢...");} catch (InterruptedException e) {e.printStackTrace();}}public void taskC() {try {latchToC.await();System.out.println("任務C執行中...");Thread.sleep(100); // 模擬任務C執行時間System.out.println("任務C執行完畢...");} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {MultiThreadTaskExecution taskExecution = new MultiThreadTaskExecution();new Thread(taskExecution::taskB).start();new Thread(taskExecution::taskC).start();new Thread(taskExecution::taskA).start();}}

線程 A、B、C 都到達屏障點才執行后續操作

實現方案:CyclicBarrier

  • 設置屏障數量 3,同時可設置一個 Runnable 任務,當都達到時輸出一句話。
public class CyclicBarrierOne {// 創建一個新的CyclicBarrier,當3個參與者到達時執行屏障操作private CyclicBarrier barrier = new CyclicBarrier(3, () -> System._out_.println("所有線程到達屏障點,屏障操作執行!"));public static void main(String[] args) {CyclicBarrierOne cyclicBarrierOne = new CyclicBarrierOne();new Thread(() -> cyclicBarrierOne.startTask(), "Thread-A").start();new Thread(() -> cyclicBarrierOne.startTask(), "Thread-B").start();new Thread(() -> cyclicBarrierOne.startTask(), "Thread-C").start();}private void startTask() {System._out_.println(Thread._currentThread_().getName() + "開始執行任務...");try {Thread._sleep_(100);} catch (InterruptedException e) {e.printStackTrace();}System._out_.println(Thread._currentThread_().getName() + "到達屏障點,等待其他線程...");try {barrier.await();} catch (Exception e) {e.printStackTrace();}System._out_.println(Thread._currentThread_().getName() + "繼續執行后續操作");}}

10 個線程同時啟動

public class SimultaneousStart {private static final int _N _= 10;_// 創建一個CountDownLatch用于線程啟動的信號_
_    _private static final CountDownLatch _startSignal _= new CountDownLatch(1);_// 創建一個 CountDownLatch 用于等待所有線程完成的信號_
_    _private static final CountDownLatch _doneSignal _= new CountDownLatch(_N_);public static void main(String[] args) throws InterruptedException {Runnable task = () -> {try {_startSignal_.await(); _// 等待啟動信號_
_                _System._out_.println(Thread._currentThread_().getName() + " has started");Thread._sleep_(2000); _// 模擬任務執行_
_                _System._out_.println(Thread._currentThread_().getName() + " has finished");} catch (InterruptedException e) {Thread._currentThread_().interrupt();} finally {_doneSignal_.countDown(); _// 完成信號_
_            _}};_// 創建并啟動N個線程_
_        _for (int i = 0; i < _N_; i++) {new Thread(task, "Thread-" + (i + 1)).start();}_// 主線程等待片刻,確保所有線程已經啟動并在等待_
_        _Thread._sleep_(1000);System._out_.println("All threads are ready, starting now!");_startSignal_.countDown(); _// 發出啟動信號_
_        doneSignal_.await(); _// 等待所有線程完成__        _System._out_.println("All threads have finished executing.");}
}

死鎖

public class DeadlockExample {// 創建兩個資源
private static final Object _resourceOne _= new Object();
private static final Object _resourceTwo _= new Object();public static void main(String[] args) {new Thread(() -> {synchronized (resourceOne) {System.out.println(Thread.currentThread().getName() + "locked resource1");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resourceTwo) {System.out.println(Thread.currentThread().getName() + "locked resource2");}}}, "Thread-A").start();new Thread(() -> {synchronized (resourceTwo) {System.out.println(Thread.currentThread().getName() + "locked resource2");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resourceOne) {System.out.println(Thread.currentThread().getName() + "locked resource1");}}}, "Thread-B").start();}}

多個線程同時爭搶同一把鎖,阻塞情況下喚醒指定線程

  • 自定義條件變量
  • 標志變量

自定義條件變量

public class CustomLockExample {private final Lock lock = new ReentrantLock();private final Condition conditionA = lock.newCondition();private final Condition conditionB = lock.newCondition();private void methodA() throws InterruptedException {lock.lock();try {System._out_.println("Thread A is waiting");conditionA.await();System._out_.println("Thread A is resumed");} finally {lock.unlock();}}private void methodB() throws InterruptedException {lock.lock();try {System._out_.println("Thread B is waiting");conditionB.await();System._out_.println("Thread B is resumed");} finally {lock.unlock();}}private void resumeA() {lock.lock();try {conditionA.signal();  _// Wake up one thread waiting on conditionA_
_            _System._out_.println("Signaled Thread A");} finally {lock.unlock();}}private void resumeB() {lock.lock();try {conditionB.signal();  _// Wake up one thread waiting on conditionB_
_            _System._out_.println("Signaled Thread B");} finally {lock.unlock();}}public static void main(String[] args) throws InterruptedException {CustomLockExample example = new CustomLockExample();Thread threadA = new Thread(() -> {try {example.methodA();} catch (InterruptedException e) {e.printStackTrace();}});Thread threadB = new Thread(() -> {try {example.methodB();} catch (InterruptedException e) {e.printStackTrace();}});threadA.start();threadB.start();Thread._sleep_(2000);  _// Pause to ensure threads reach wait state__        _example.resumeA();   _// Signal threadA_
_        _Thread._sleep_(2000);example.resumeB();   _// Signal threadB_
_    _}
}

標志變量

public class FlagBasedControl {private final Object lock = new Object();private volatile boolean isThreadAWake = false;private void methodA() throws InterruptedException {synchronized (lock) {while (!isThreadAWake) {System._out_.println("Thread A is waiting");lock.wait();}}System._out_.println("Thread A is resumed and resetting flag");isThreadAWake = false;  _// Reset the flag for next use    }_
_    _}private void resumeA() {synchronized (lock) {isThreadAWake = true;lock.notifyAll();  _// Wake up all threads, but only Thread A will proceed_
_            _System._out_.println("Signaled Thread A");}}public static void main(String[] args) throws InterruptedException {FlagBasedControl example = new FlagBasedControl();Thread threadA = new Thread(() -> {try {example.methodA();} catch (InterruptedException e) {Thread._currentThread_().interrupt();}});threadA.start();Thread._sleep_(2000);  _// Pause to ensure thread reaches wait state__        _example.resumeA();  _// Signal threadA_
_    _}
}

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

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

相關文章

Linux夢開始的地方

1.概率 經過C語言&#xff0c;數據結構&#xff0c;C的學習我們現在要開始學習Linux的學習了。我們學習Linux是從四部分來進行的&#xff1a; 1.Linux初識&#xff0c;Linux環境&#xff0c;Linux指令&#xff0c;Linux開發環境。 2.Linux系統。 3.Linux網絡 4.MySQL Lin…

“二維前綴和”算法原理及模板

在學習本篇內容前建議先學習一下“一維前綴和” 一維前綴和 算法https://blog.csdn.net/czt230610/article/details/148012923?fromshareblogdetail&sharetypeblogdetail&sharerId148012923&sharereferPC&sharesourceczt230610&sharefromfrom_link接下來…

軟件設計師CISC與RISC考點分析——求三連

一、考點分值占比與趨勢分析&#xff08;CISC與RISC&#xff09; 綜合知識分值統計表 年份考題數量分值分值占比考察重點2018111.33%指令特征對比2019111.33%控制器實現方式2020222.67%寄存器數量/流水線技術2021111.33%尋址方式對比2022222.67%指令復雜度/譯碼方式2023111.3…

順 序 表:數 據 存 儲 的 “ 有 序 陣 地 ”

順 序 表&#xff1a;數 據 存 儲 的 “ 有 序 陣 地 ” 線 性 表順 序 表 - - - 順 序 存 儲 結 構順 序 表 的 操 作 實 現代 碼 全 貌 與 功 能 介 紹順 序 表 的 功 能 說 明代 碼 效 果 展 示代 碼 詳 解SeqList.hSeqList.ctest.c 總 結 &#x1f4bb;作 者 簡 介&#xf…

網絡安全深度解析:21種常見網站漏洞及防御指南

一、高危漏洞TOP 10 1. SQL注入(SQLi) 原理:通過構造惡意SQL語句突破系統過濾機制 典型場景: - 聯合查詢注入: union select 1,version(),3--+ - 布爾盲注:and (select substr(user(),1,1)=r) - 時間盲注:;if(now()=sysdate(),sleep(5),0)/ 防御方案: - 嚴格參數化查…

代碼上傳gitte倉庫

把代碼push上去就行

創建型:單例模式

目錄 1、核心思想 2、實現方式 2.1 餓漢式 2.2 懶漢式 2.3 枚舉&#xff08;Enum&#xff09; 3、關鍵注意事項 3.1 線程安全 3.2 反射攻擊 3.3 序列化與反序列化 3.4 克隆保護 4、適用場景 1、核心思想 目的&#xff1a;確保一個類僅有一個實例 功能&#xff1a;…

副業小程序YUERGS,從開發到變現

文章目錄 我為什么寫這個小程序網站轉小程序有什么坑有什么推廣渠道個人開發者如何變現簡單介紹YUERGS小程序給獨立開發者一點小建議 我為什么寫這個小程序 關注我的粉絲應該知道&#xff0c;我在碩士階段就已經掌握了小程序開發技能&#xff0c;并寫了一個名為“約球online”…

React路由(React學習筆記_09)

React路由 1,路由基礎 現代的前端應用大多都是SPA(單頁應用程序)&#xff0c;也就是只有一個HTML頁面的應用程序。因為它的用戶體驗更好、對服務器的壓力更小&#xff0c;所以更受歡迎。為了有效的使用單個頁面來管理原來多個頁面的功能&#xff0c;前端路由應運而生。 1, 安裝…

2009-2025計算機408統考真題及解析

整理2009-2025 年計算機408統考真題及解析PDF 目錄樹&#xff1a; └── 2025考研計算機408統考真題及答案&#xff08;回憶版&#xff09;.pdf ├── 2009-2024計算機408真題解析 │ ├── 2009年計算機408統考真題解析.pdf │ ├── 2010年計算機408統考真題解析.pdf …

Mysql、Oracle、Sql Server、達夢之間sql的差異

1&#xff1a;分頁查詢 Sql Server&#xff1a; <bind name"startRow" value"(page - 1) * limit 1"/> <bind name"endRow" value"page * limit"/> SELECT *FROM (SELECT ROW_NUMBER() OVER (<if test"sortZd!…

SQL Server 常用函數

一、字符串處理函數 1. CONCAT&#xff1a;拼接字符串 語法&#xff1a;CONCAT(string1, string2, ..., stringN) 實例&#xff1a; SELECT CONCAT(Hello, , World) AS Result; 輸出&#xff1a; Result ------------- Hello World 2. SUBSTRING&#xff1a;截取子字符串 …

【通用大模型】Serper API 詳解:搜索引擎數據獲取的核心工具

Serper API 詳解&#xff1a;搜索引擎數據獲取的核心工具 一、Serper API 的定義與核心功能二、技術架構與核心優勢2.1 技術實現原理2.2 對比傳統方案的突破性優勢 三、典型應用場景與代碼示例3.1 SEO 監控系統3.2 競品廣告分析 四、使用成本與配額策略五、開發者注意事項六、替…

ABP vNext 多租戶系統實現登錄頁自定義 Logo 的最佳實踐

&#x1f680; ABP vNext 多租戶系統實現登錄頁自定義 Logo 的最佳實踐 &#x1f9ed; 版本信息與運行環境 ABP Framework&#xff1a;v8.1.5.NET SDK&#xff1a;8.0數據庫&#xff1a;PostgreSQL&#xff08;支持 SQLServer、MySQL 等&#xff09;BLOB 存儲&#xff1a;本地…

FastDFS分布式文件系統架構學習(一)

FastDFS分布式文件系統架構學習 1. FastDFS簡介 FastDFS是一個開源的輕量級分布式文件系統&#xff0c;由淘寶資深架構師余慶設計并開發。它專為互聯網應用量身定制&#xff0c;特別適合以中小文件&#xff08;如圖片、文檔、音視頻等&#xff09;為載體的在線服務。FastDFS不…

基于單片機的防盜報警器設計與實現

標題:基于51單片機的防盜報警器設計 內容:1.摘要 本文圍繞基于51單片機的防盜報警器設計展開。背景在于現代社會安全需求不斷提高&#xff0c;傳統防盜方式存在諸多不足。目的是設計一款成本低、可靠性高且易于使用的防盜報警器。方法上&#xff0c;以51單片機為核心控制單元&…

IDE/IoT/搭建物聯網(LiteOS)集成開發環境,基于 LiteOS Studio + GCC + JLink

文章目錄 概述LiteOS Studio不推薦&#xff1f;安裝和使用手冊呢?HCIP實驗的源碼呢&#xff1f; 軟件和依賴安裝軟件下載軟件安裝插件安裝依賴工具-方案2依賴工具-方案1 工程配置打開或新建工程板卡配置組件配置編譯器配置-gcc工具鏈編譯器配置-Makefile腳本其他配置編譯完成 …

【高斯擬合最終篇】Levenberg-Marquardt(LM)算法

Levenberg-Marquardt(LM)算法是一種結合高斯-牛頓法和梯度下降法的優化方法,特別適合非線性最小二乘問題,如高斯函數擬合。它通過引入阻尼因子(damping factor)平衡高斯-牛頓法的快速收斂和梯度下降法的穩定性。以下是基于之前的 gaussian_fit.py,加入 LM 算法實現高斯擬…

信道編碼技術介紹

信息與通信系統中的編碼有4 種形式&#xff1a;信源編碼、信道編碼、密碼編碼和多址編碼。 其中信道編碼的作用是對信源經過壓縮后的數據加一定數量受到控制的冗余&#xff0c;使得數據在傳輸中或接收中發生的差錯可以被糾正或被發現&#xff0c;從而可以正確恢復出原始數據信息…

線性回歸策略

一種基于ATR(平均真實范圍)、線性回歸和布林帶的交易策略。以下是對該策略的全面總結和分析: 交易邏輯思路 1. 過濾條件: - 集合競價過濾:在每個交易日的開盤階段,過濾掉集合競價產生的異常數據。 - 價格異常過濾:排除當天開盤價與最高價或最低價相同的情況,這…