多執行緒中使用Lock鎖定多個條件Condition的使用
Lock
公平鎖
所謂公平鎖就是按照申請鎖的順序來執行,就像排隊取款一樣,前面的人取款結束後面的人才可以取,就是一個佇列。
非公平鎖
非公平鎖是指多個執行緒獲取鎖的順序並不是按照申請鎖的順序,與上面相反有可能後申請鎖的反而先獲得了鎖導致優先順序翻轉;也會出現某個執行緒一直拿不到鎖導致執行緒飢餓現象。
非公平鎖的優點在於吞吐量比公平鎖大,synchronized
就是一種非公平鎖
鎖的使用ReentrantLock
ReentrantLock實現了Lock介面,使用時他有無參構造方法和有參構造方法。
無參構造放從原始碼可以看出是呼叫的NonfairSync()
方法,這是一個非公平鎖從名字就可以看出。
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
有參構造方法是接收一個boolean
型別變數。從程式碼可以看出傳true
時例項化的是公平鎖,傳false
時例項化的是非公平鎖。
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
Condition
Condition
裡的await()
、signal()
、signalAll()
與Object
監視器方法裡的( wait()
, notify()
和notifyAll()
)類似。Lock
可替換synchronized
方法和語句的使用, Condition
取代了物件監視器方法的使用。
Condition的常用方法
方法 | 描述 |
---|---|
await() | 使當前執行緒進入掛起等待狀態,等待訊號繼續進行。 |
signal() | 喚醒一個等待執行緒。 |
signalAll() | 喚醒所有等待執行緒。 |
Lock繫結多個Condition使用
這裡做一個鏈式喚醒的操作,流程圖如下
鎖的三部曲: 判斷 幹活 喚醒
裡面的判斷為了避免虛假喚醒,一定要採用 while
案例: 做個公司招人面試的流程
- 來個一個求職者hr先面試問幾個問題
- manager再面試問幾個問題
- boss面試問幾個問題,沒有通過告知hr繼續招人
此時三個面試官分別是三個執行緒,按照順序來。模擬面試6個求求職者。(不要糾結為啥都沒通過,只是演示)
建立一個標識
// 標誌位 0:hr 1:manager 2:boss
private int flag = 0;
建立一把重入鎖
// 建立一個重入鎖
private Lock lock = new ReentrantLock();
給這把鎖建立三把鑰匙
// 這三個相當於備用鑰匙
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
- 判斷 判斷標識位是否成立否則就進入掛起等待狀態
- 幹活 面試官提問問題
- 通知 前一個面試官面試完通知下一個面試官
求職業務類完整程式碼Interview
package com.avatar.juc.sample1;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 面試需要的流程
* 1、hr 提問三個問題
* 2、manager 提問五個問題
* 3、boss 提問兩個問題
* 微信公眾號:快樂學習與分享
*/
public class Interview {
// 標誌位 0:hr 1:manager 2:boss
private int flag = 0;
// 建立一個重入鎖
private Lock lock = new ReentrantLock();
// 這三個相當於備用鑰匙
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
/**
* hr 面試
* @param num 面試者序號
*/
public void hrAsk3(int num){
lock.lock();
try {
// 1、判斷flag不等於0是掛起
while (flag != 0){ // 為了避免虛假喚醒,一定要採用 while
c1.await();
}
System.out.println(Thread.currentThread().getName() + "\t面試第:" + num + "位面試者");
// 2、工作 hr提問
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + "\t提問第:" + i + "個問題");
}
// 3、通知 進入下個流程
flag = 1;
c2.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
/**
* manger 面試
* @param num 面試者序號
*/
public void mangerAsk5(int num){
lock.lock();
try {
// 1、判斷flag不等於1是掛起
while (flag != 1){ // 為了避免虛假喚醒,一定要採用 while
c2.await();
}
System.out.println(Thread.currentThread().getName() + "\t面試第:" + num + "位面試者");
// 2、工作 manger 提問
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + "\t提問第:" + i + "個問題");
}
// 3、通知 進入下個流程
flag = 2;
c3.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
/**
* boss 面試
* @param num 面試者序號
*/
public void bossAsk3(int num){
lock.lock();
try {
// 1、判斷flag不等於2是掛起
while (flag != 2){ // 為了避免虛假喚醒,一定要採用 while
c3.await();
}
System.out.println(Thread.currentThread().getName() + "\t面試第:" + num + "位面試者");
// 2、工作 hr提問
for (int i = 1; i <= 2; i++) {
System.out.println(Thread.currentThread().getName() + "\t提問第:" + i + "個問題");
}
System.out.println("很可惜,沒通過。。。");
System.out.println("");
// 3、通知 進入下個流程
flag = 0;
c1.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
模擬6個人面試測試類完整程式碼LockAndConditionDemo
package com.avatar.juc.sample1;
/**
* 微信公眾號:快樂學習與分享
*
* Lock鎖繫結多個條件condition
*
* 案例:面試者面試流程為例,一個面試者來到
* hr 先面試 提問3個問題 -> manager 再面試提問5個問題 -> boss最後面試提問2個問題
* hr 先面試 提問3個問題 -> manager 再面試提問5個問題 -> boss最後面試提問2個問題
* hr 先面試 提問3個問題 -> manager 再面試提問5個問題 -> boss最後面試提問2個問題
* 。。。。。。
*
* 假如共面試6個人(案例只為演示)
*/
public class LockAndConditionDemo {
public static void main(String[] args) {
Interview interview = new Interview();
new Thread(()->{
for (int i = 1; i <= 6; i++) {
interview.hrAsk3(i);
}
},"hr").start();
new Thread(()->{
for (int i = 1; i <= 6; i++) {
interview.mangerAsk5(i);
}
},"manager").start();
new Thread(()->{
for (int i = 1; i <= 6; i++) {
interview.bossAsk3(i);
}
},"boss").start();
}
}
測試列印結果
hr 面試第:1位面試者
hr 提問第:1個問題
hr 提問第:2個問題
hr 提問第:3個問題
manager 面試第:1位面試者
manager 提問第:1個問題
manager 提問第:2個問題
manager 提問第:3個問題
manager 提問第:4個問題
manager 提問第:5個問題
boss 面試第:1位面試者
boss 提問第:1個問題
boss 提問第:2個問題
沒通過。。。
hr 面試第:2位面試者
hr 提問第:1個問題
hr 提問第:2個問題
hr 提問第:3個問題
manager 面試第:2位面試者
manager 提問第:1個問題
manager 提問第:2個問題
manager 提問第:3個問題
manager 提問第:4個問題
manager 提問第:5個問題
boss 面試第:2位面試者
boss 提問第:1個問題
boss 提問第:2個問題
沒通過。。。
......
瞭解更多:
相關文章
- java多執行緒與併發 - Condition(條件)Java執行緒
- Java多執行緒學習(六)Lock鎖的使用Java執行緒
- 多執行緒與併發-----條件阻塞Condition的應用執行緒
- Linux Qt使用POSIX多執行緒條件變數、互斥鎖(量)LinuxQT執行緒變數
- 如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?ReentrantLock變數執行緒
- 多執行緒-JDK5之後的Lock鎖的概述和使用執行緒JDK
- Java多執行緒11:ReentrantLock的使用和ConditionJava執行緒ReentrantLock
- ArcGISEngine中的多執行緒使用執行緒
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- 多執行緒06:條件變數執行緒變數
- 多執行緒與併發-----Lock鎖技術執行緒
- Linux多執行緒的使用一:互斥鎖Linux執行緒
- Java多執行緒-鎖的區別與使用Java執行緒
- 多執行緒使用執行緒
- Java多執行緒/併發06、執行緒鎖Lock與ReadWriteLockJava執行緒
- 多執行緒_鎖執行緒
- Java多執行緒-執行緒池的使用Java執行緒
- iOS多執行緒的使用iOS執行緒
- 多執行緒:barrier的使用執行緒
- 使用多執行緒實現郵件傳送執行緒
- 多執行緒-死鎖問題概述和使用執行緒
- 多執行緒-定時器的概述和使用執行緒定時器
- java使用多執行緒Java執行緒
- 使用委託開啟多執行緒(多執行緒深入)執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- Python執行緒條件變數Condition解析Python執行緒變數
- java多執行緒之執行緒的基本使用Java執行緒
- 多執行緒-執行緒組的概述和使用執行緒
- 多執行緒-執行緒池的概述和使用執行緒
- linux程式多執行緒互斥鎖的簡單使用Linux執行緒
- python多執行緒程式設計3: 使用互斥鎖同步執行緒Python執行緒程式設計
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- Java多執行緒的使用(二)Java執行緒
- C#中多執行緒 委託的使用C#執行緒
- Android小知識-Java多執行緒相關(Lock使用)AndroidJava執行緒
- 多執行緒,到底該設定多少個執行緒?執行緒
- IOS下使用多執行緒iOS執行緒
- 多執行緒鎖的問題執行緒