1. 公平鎖,線程排序執行,防餓死應用場景
公平鎖原則必須按照鎖申請時間上先到先得的原則分配機制場景;
1).實現邏輯 上(包括:軟件中函數計算、業務先後流程;硬件中操作實現中順序邏輯)的順序排隊機制的場景;
軟件場景:用戶交互View中對用戶輸入結果分析類,分析過程後面算法依賴上一步結果的場景,例如:推薦算法實現[根據性別、年齡篩選]、阻塞隊列的實現;
硬件場景:需要先分析確認用戶操作類型硬件版本或者廠家,然後發出操作指令;例如:自動售貨機;
2).現實 生活中 時間排序的 公平原則:
例如:客服分配,必須是先到先服務,不能出現餓死現象;公平鎖實現見上文:
公平鎖與非公平鎖的測試demo:邏輯代碼實現那就沒法子實現了;
阻塞隊列的實現就是時間上的公平原則。
2. 非公平鎖,效率的體現者
實際開發中最常用的的場景就是非公平鎖,ReentrantLock無參構造默認就時候非公平鎖;適應場景除了上面公平鎖中提到的其他都是非公平鎖的使用場景;
3. ReentrantLock.Condition線程通信
ReentrantLock.Condition線程通信是最長見的面試題,這裏以最簡單例子:兩個線程之間交替打印 26英文字母和阿拉伯數字爲demo:
private void alternateTask() {
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Thread thread1 = new Thread(() -> {
try {
lock.lock();
for (int i = 65; i < 91; i++) {
System.out.println("----------thread1------- " + (char) i);
condition2.signal();
condition1.await();
}
condition2.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
});
Thread thread2 = new Thread(() -> {
try {
lock.lock();
for (int i = 0; i < 26; i++) {
System.out.println("----------thread2------- " + i);
condition1.signal();
condition2.await();
}
condition1.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
});
thread1.start();
thread2.start();
}
4.同步功能的使用
實現線程同步鎖synchronized 功能【單例爲例】
private Singleton() {
}
private static Singleton instance;
private static Lock lock = new ReentrantLock();
public static Singleton getInstance() {
lock.lock();
try {
if (instance == null) {
instance = new Singleton();
}
} finally {
lock.unlock();
}
return instance;
}
5. 中斷殺器應用
ReentrantLock中lockInterruptibly()和lock()最大的區別就是中斷相應問題:
lock()是支持中斷相應的阻塞試的獲取方式,因此即使主動中斷了鎖的持有者,但是它不能立即unlock(),仍然要機械版執行完所有操作纔會釋放鎖。
lockInterruptibly()是 優先響應中斷的,這樣有個優勢就是可以通過tryLock()、tryLock(timeout, TimeUnit.SECONDS)方法,中斷優先級低的Task,及時釋放資源給優先級更高的Task,甚至看到網上有人說可以做防止死鎖的優化;
ReentrantLock lock = new ReentrantLock();
try {
lock.lockInterruptibly();
if (lock.tryLock(timeout, TimeUnit.SECONDS)) {
//TODO
}else{
//超時直接中斷優先級低的Task
Thread.currentThread().interrupt();
lock.lock();
//TODO
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
6. 非重要任務Lock使用
優先級較低的操作讓步給優先級更高的操作,提示代碼效率/用戶體驗;忽略重複觸發
1).用在定時任務時,如果任務執行時間可能超過下次計劃執行時間,確保該有狀態任務只有一個正在執行,忽略重複觸發。
2).用在界面交互時點擊執行較長時間請求操作時,防止多次點擊導致後臺重複執行(忽略重複觸發)。
以上兩種情況多用於進行非重要任務防止重複執行,(如:清除無用臨時文件,檢查某些資源的可用性,數據備份操作等)
tryLock()功能:如果已經獲得鎖立即返回fale,起到防止重複而忽略的效果
ReentrantLock lock = new ReentrantLock();
//防止重複執行,執行耗時操作,例如用戶重複點擊
if (lock.tryLock()) {
try {
//TO DO
} finally {
lock.unlock();
}
}
超時放棄
定時操作的例如:錯誤日誌、定時過期緩存清理的操作,遇到優先級更高的操作佔用資源時,暫時放棄本次操作下次再處理,可以起到讓出CPU,提升用戶體驗;
ReentrantLock lock = new ReentrantLock();
try {
if (lock.tryLock(timeout, TimeUnit.SECONDS)) {
//TO DO
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}