Java中Lock鎖基本使用方法詳解
一、Lock鎖的基本使用
在Java中,Lock是一個接口,它提供了比synchronized關鍵字更高級的線程同步機制。使用Lock接口可以創(chuàng)建更復雜和靈活的同步結(jié)構(gòu)。
Lock接口的常用實現(xiàn)類有ReentrantLock和ReentrantReadWriteLock,它們提供了可重入的互斥鎖和讀寫鎖。
使用Lock鎖的一般步驟如下:
1. 創(chuàng)建一個`Lock`對象實例。
Lock lock = new ReentrantLock();
2. 在需要進行同步的代碼塊中,通過調(diào)用`lock()`方法來獲取鎖。
lock.lock(); try { // 同步的代碼 } finally { // 在finally塊中釋放鎖,以確保鎖的釋放 lock.unlock(); }
3. 在同步的代碼塊執(zhí)行完之后,通過調(diào)用`unlock()`方法釋放鎖。示例代碼:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Main { private static Lock lock = new ReentrantLock(); public static void main(String[] args) { Thread t1 = new Thread(() -> { acquireLock(); }); Thread t2 = new Thread(() -> { acquireLock(); }); t1.start(); t2.start(); } private static void acquireLock() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + " 獲取到了鎖"); // 執(zhí)行同步的代碼塊 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName() + " 釋放了鎖"); lock.unlock(); // 釋放鎖 } } } ``` 輸出: ``` Thread-0 獲取到了鎖 Thread-0 釋放了鎖 Thread-1 獲取到了鎖 Thread-1 釋放了鎖 ```
在上述示例中,我們創(chuàng)建了一個ReentrantLock實例作為鎖對象。然后,我們創(chuàng)建兩個線程t1和t2,它們都會調(diào)用acquireLock()方法獲取鎖并執(zhí)行同步的代碼塊。最后,我們可以看到兩個線程交替地獲取到鎖、執(zhí)行同步代碼塊并釋放鎖。
需要注意的是,在使用Lock接口時要注意在finally塊中釋放鎖,以確保在任何情況下都能正常釋放鎖。否則可能會導致線程出現(xiàn)死鎖的情況。
使用Lock鎖可以靈活控制線程的同步和互斥,并提供了更多的高級功能,例如可中斷的鎖、條件變量等,可以更好地實現(xiàn)復雜的并發(fā)控制需求。
二、Condition類詳解
在Java中,Condition類是Java.util.concurrent包下的一個接口,用于支持線程的等待和通知機制。它通常與Lock接口一起使用,用于實現(xiàn)線程間的同步和協(xié)調(diào)。
Condition類提供了以下方法:
1. await():使當前線程等待,直到被其他線程調(diào)用signal()或signalAll()方法喚醒。
2. awaitUninterruptibly():類似于await()方法,但是在等待期間不會響應線程中斷。
3. await(long time, TimeUnit unit):使當前線程等待一段時間,在指定的時間內(nèi)沒有被其他線程調(diào)用signal()或signalAll()方法喚醒,將自動喚醒。
4. awaitNanos(long nanosTimeout):使當前線程等待一段納秒時間,在指定的時間內(nèi)沒有被其他線程調(diào)用signal()或signalAll()方法喚醒,將自動喚醒。
5. awaitUntil(Date deadline):使當前線程等待直到某個時間,如果在指定時間內(nèi)沒有被其他線程調(diào)用signal()或signalAll()方法喚醒,將自動喚醒。
6. signal():喚醒一個等待在Condition上的線程,并使其從await()方法返回。
7. signalAll():喚醒所有等待在Condition上的線程,并使它們從await()方法返回。使用示例:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionExample { private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void doSomething() { lock.lock(); try { // 等待條件 condition.await(); // 執(zhí)行其他操作 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void notifyThread() { lock.lock(); try { // 喚醒線程 condition.signal(); } finally { lock.unlock(); } } }
在上述示例中,使用lock對象創(chuàng)建了一個Condition實例condition。在doSomething()方法中,線程將調(diào)用condition.await()進入等待狀態(tài),直到其他線程調(diào)用condition.signal()方法喚醒它。notifyThread()方法用于喚醒等待在condition上的線程。
這樣,通過Condition類的使用,我們可以實現(xiàn)線程之間的等待和通知機制,實現(xiàn)更靈活的線程同步與協(xié)調(diào)。
三、進程的優(yōu)先級
在Java中,可以使用Thread類的setPriority(int priority)方法來設置線程的優(yōu)先級。Java中的線程優(yōu)先級范圍是1(最低優(yōu)先級)到10(最高優(yōu)先級),其中5為默認優(yōu)先級。
一個線程的優(yōu)先級僅僅是給調(diào)度器一個提示,告訴它該如何調(diào)度線程,實際上是由操作系統(tǒng)來決定如何處理線程的優(yōu)先級。不同操作系統(tǒng)可能會有不同的處理方式,且并不能保證線程優(yōu)先級會完全按照設定的順序高低執(zhí)行。
以下是設置線程優(yōu)先級的示例代碼:
package lzx6; public class ThreadPriorityExample { public static void main(String[] args) { Thread thread1 = new Thread(() -> { for (int i = 0;; i++) { System.out.println("Thread 1: " + i); } }); Thread thread2 = new Thread(() -> { for (int i = 0;;i++ ) { System.out.println("Thread 2: " + i); } }); // 設置線程的優(yōu)先級 thread1.setPriority(Thread.MIN_PRIORITY); // 最低優(yōu)先級 thread2.setPriority(Thread.MAX_PRIORITY); // 最高優(yōu)先級 // 啟動線程 thread1.start(); thread2.start(); } }
運行結(jié)果:
可以看到確實進程2的優(yōu)先級更高。
在上述代碼中,我們創(chuàng)建了兩個線程thread1和thread2,分別輸出各自線程標識和循環(huán)變量的值。我們通過調(diào)用thread1.setPriority(Thread.MIN_PRIORITY)設置thread1線程為最低優(yōu)先級,通過調(diào)用thread2.setPriority(Thread.MAX_PRIORITY)設置`thread2`線程為最高優(yōu)先級。
需要注意的是,線程的優(yōu)先級只是給調(diào)度器提供了一個提示,不同的操作系統(tǒng)可能有不同的實現(xiàn)方式,而且不能保證線程會按照設定的優(yōu)先級順序執(zhí)行。此外,線程優(yōu)先級的相對差異通常只在較忙碌的系統(tǒng)中才能明顯體現(xiàn)出來,在負載較輕的系統(tǒng)中可能不會有明顯的效果。Oracle提供的Linux的Java虛擬機中,線程優(yōu)先級都是一樣的。
四、wait/join與sleep的區(qū)別:
wait(), join(), 和 sleep() 是用于控制線程執(zhí)行的方法,它們在用途和行為上有一些區(qū)別。
1. wait(): 是Object類的方法,用于使當前線程進入等待狀態(tài),直到其他線程調(diào)用相同對象上的notify()或notifyAll()方法來喚醒等待的線程。wait()方法必須在同步代碼塊或同步方法中調(diào)用。
2. join(): 是Thread類的方法,用于等待調(diào)用join()方法的線程執(zhí)行完畢。當一個線程調(diào)用其他線程的join()方法時,當前線程會進入等待狀態(tài),直到被調(diào)用的線程執(zhí)行完畢。join()方法通常用于多線程協(xié)作,以確保線程執(zhí)行的順序。
3. sleep(): 是Thread類的方法,用于使當前線程進入休眠狀態(tài)(阻塞),暫時中止執(zhí)行一段時間。sleep()方法會讓線程暫停執(zhí)行指定的時間,然后重新進入可運行狀態(tài)。
關鍵區(qū)別如下:
- - wait()和join()方法都依賴于其他線程的操作,而`sleep()方法是通過指定的時間來控制線程執(zhí)行。
- - wait()方法在等待期間會釋放對象的鎖,而sleep()方法和join()方法在等待期間仍然持有對象的鎖。
- - wait()方法必須在同步代碼塊或同步方法中調(diào)用,而sleep()方法和join()方法可以在任何地方調(diào)用。
- - wait()方法需要被喚醒后才能繼續(xù)執(zhí)行,而sleep()方法和join()方法可以在指定的時間過去后自動繼續(xù)執(zhí)行。
總結(jié)來說,wait()方法和join()方法是用于線程間的通信和協(xié)作,sleep()方法是用于控制線程執(zhí)行時間的暫停。
總結(jié)
到此這篇關于Java中Lock鎖基本使用方法詳解的文章就介紹到這了,更多相關Java Lock鎖詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java集合List快速實現(xiàn)重復判斷的方法小結(jié)
在java編寫代碼中經(jīng)常會遇到某些重復判定或者去重的操作,本文主要為大家介紹了幾個常用方法,感興趣的小伙伴可以跟隨不想一起學習一下2024-12-12mybatis-plus自帶QueryWrapper自定義sql實現(xiàn)復雜查詢實例詳解
MyBatis-Plus是一個MyBatis(opens new window)的增強工具,在 MyBatis的基礎上只做增強不做改變,MyBatis可以無損升級為MyBatis-Plus,這篇文章主要給大家介紹了關于mybatis-plus自帶QueryWrapper自定義sql實現(xiàn)復雜查詢的相關資料,需要的朋友可以參考下2022-10-10Spring?main方法中如何調(diào)用Dao層和Service層的方法
這篇文章主要介紹了Spring?main方法中調(diào)用Dao層和Service層的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12