如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?
如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?
一. 前言
近日有學生在參加某公司校招面試時,遇到一個多個執行緒順序執行的面試題,特意記錄下來和大家分享一下,這個題目的具體要求是這樣的:
假設有3個執行緒 a,b,c,要求三個執行緒一起進入到就緒態,執行時一定要按照 a-->b-->c的順序執行。即使a或者b執行緒進入到了阻塞態,也一定會按照a-->b-->c的順序執行執行緒。請問該如何保證實現這個需求呢?
二. 解決方案
關於這道題,網上常見的實現思路,大致有4種解決方案:
- 透過join()方法使當前執行緒“阻塞”,等待指定執行緒執行完畢後繼續執行;
- 透過倒數計時器CountDownLatch實現;
- 透過建立單一化執行緒池 newSingleThreadExecutor()實現;
- 透過ReentrantLock 中的條件變數實現;
今天先使用ReentrantLock 的條件變數來實現這個題目中的需求。
三. 使用ReentrantLock 條件變數
首先我們們來了解一下,什麼是ReentrantLock 條件變數(Condition)。
ReentrantLock 中的條件變數功能,類似於普通 synchronized 的 wait、notify,我們可以使用Reentrantlock 鎖,配合 Condition 物件上的 await()和 signal()或 signalAll()方法,來實現執行緒間協作。與synchronized的wait和notify不同之處在於,ReentrantLock中的條件變數可以有多個,可以實現更精細的控制執行緒。
Condition中常用的方法API有如下這些:
ReentrantLock程式碼實現:
class ShareDataLock{
// 執行緒執行的條件 1:執行緒1執行 2:執行緒2執行 3:執行緒3執行
int number =1;
// 鎖
Lock lock = new ReentrantLock();
// 從鎖中獲得3個條件變數
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
// 第一個執行緒run之後執行的方法
public void f1(){
lock.lock();
try {
// 如果條件值不為1 就掛起等待
while(number!=1){
condition1.await();
}
// 故意阻塞100毫秒,看看其他的執行緒會不會不再排隊
Thread.sleep(100);
System.out.println("------1--------");
// 執行緒1 執行完畢 把變數設定為2
number = 2;
// 喚醒第2個條件變數
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 不管拋沒丟擲異常都要解鎖,防止執行緒死鎖
lock.unlock();
}
}
public void f2(){
lock.lock();
try {
while(number!=2){
condition2.await();
}
System.out.println("------2--------");
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void f3(){
lock.lock();
try {
while(number!=3){
condition3.await();
}
System.out.println("------3--------");
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class SynchronizedAndReentrantLockDemo {
public static void main(String[] args) {
ShareDataLock shareDataLock = new ShareDataLock();
for (int i = 0; i < 10; i++) {
// 3個執行緒分別執行1,2,3 3個方法 ,並且同時就緒
new Thread(()->shareDataLock.f1(),"AA").start();
new Thread(()->shareDataLock.f2(),"bb").start();
new Thread(()->shareDataLock.f3(),"cc").start();
}
}
}
程式碼執行效果如下圖:
現在我們就會發現,3個執行緒已經可以被隨意控制了,你會了嗎?
四. 後話
如上文所述,讓多個執行緒按順序執行,網上常見的解決方案有4種。但大家要注意的是,面試官出這個題有一個先決條件,“ 要讓所有的執行緒同時就緒”,所以我們就可以排除使用join方法和使用單一化執行緒池的方案了。那麼要想實現這個面試題中的需求,比較靠譜的方法 只剩下ReentrantLock 中的條件變數和使用倒數計時器CountDownLatch兩種方案了。
今天我們們暫時先介紹條件變數的方法,日後的文章中會介紹怎樣使用CountDownLatch,讓多個執行緒有序執行,敬請各位粉絲們繼續期待哦。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70023145/viewspace-2922446/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- 多執行緒06:條件變數執行緒變數
- 【java】【多執行緒】睡眠/守護/加入/禮讓執行緒,執行緒優先順序(4)Java執行緒
- Linux Qt使用POSIX多執行緒條件變數、互斥鎖(量)LinuxQT執行緒變數
- Python執行緒專題10:queue、多執行緒按順序執行Python執行緒
- 多執行緒程式設計介紹-條件變數執行緒程式設計變數
- Python執行緒條件變數Condition解析Python執行緒變數
- Java中如何保證執行緒順序執行Java執行緒
- kafka多執行緒順序消費Kafka執行緒
- 多執行緒中使用Lock鎖定多個條件Condition的使用執行緒
- Python執行緒專題7:條件變數Python執行緒變數
- Java 多執行緒基礎(十一)執行緒優先順序和守護執行緒Java執行緒
- java多執行緒6:ReentrantLockJava執行緒ReentrantLock
- 聊聊如何讓springboot攔截器的執行順序按我們想要的順序執行Spring Boot
- 多優先順序執行緒池實踐執行緒
- spring-kafka多執行緒順序消費SpringKafka執行緒
- 多執行緒實現順序迴圈列印執行緒
- 多執行緒之ReentrantLock篇(五)執行緒ReentrantLock
- join、volatile、newSingleThreadLatch 實現執行緒順序執行thread執行緒
- 【高併發】深入理解執行緒的執行順序執行緒
- 多執行緒執行任務時,某個執行緒拋異常,如何讓程式立即退出執行緒
- Pytest 順序執行,依賴執行,引數化執行
- 利用訊號量實現執行緒順序執行執行緒
- Java多執行緒-執行緒池的使用Java執行緒
- 1v1影片原始碼,你知道如何實現多執行緒的順序執行嗎?原始碼執行緒
- 如何建立多條執行緒,形成程序扇(多叉數)執行緒
- Java之執行緒的優先順序Java執行緒
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- java多執行緒之執行緒的基本使用Java執行緒
- 如何讓兩個執行緒交替列印數字執行緒
- Java 多執行緒基礎(八)執行緒讓步Java執行緒
- js函式和變數的執行順序【易錯】JS函式變數
- pipeline的執行順序
- mySQL 執行語句執行順序MySql
- 瀏覽器執行緒執行順序,瞭解一下瀏覽器執行緒
- Sql執行順序SQL
- 多執行緒--執行緒管理執行緒
- 執行緒與多執行緒執行緒