溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java中ReentrantLock類如何使用

發(fā)布時間:2020-10-10 18:38:51 來源:億速云 閱讀:143 作者:小新 欄目:編程語言

這篇文章主要介紹java中ReentrantLock類如何使用,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

在 Java 多線程中, 可以使用 synchronized 關(guān)鍵字來實現(xiàn)多線程之間同步互斥, 但在 JDK 1.5 中新增加了 ReentrantLock 類也能達到同樣的效果, 并且在擴展功能上也更加強大, 比如具有嗅探鎖定, 多路分支通知, 公平鎖和非公平鎖等(默認)功能, 而且在使用上也比 synchronized 更加的靈活.

使用 ReentrantLock 實現(xiàn)同步

public class MyService {
    private Lock lock = new ReentrantLock();
    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 10; i++){
            System.out.println("ThreadName=" + Thread.currentThread().getName() + (" " + (i + 1)));
        }
        lock.unlock();
    }
}
public class MyThread extends Thread {
    private MyService myService;
    public MyThread(MyService myService) {
        this.myService = myService;
    }
    @Override
    public void run() {
        myService.testMethod();
    }
}
public static void main(String[] args) throws IOException, InterruptedException {
MyService myService = new MyService();
MyThread myThreadA = new MyThread(myService);
        MyThread myThreadB = new MyThread(myService);
        MyThread myThreadC = new MyThread(myService);
        MyThread myThreadD = new MyThread(myService);
        MyThread myThreadE = new MyThread(myService);

        myThreadA.start();
        myThreadB.start();
        myThreadC.start();
        myThreadD.start();
        myThreadE.start();

    }

調(diào)用 ReentrantLock 對象的 lock() 方法獲取鎖, 調(diào)用 unLock() 方法釋放鎖.

從運行結(jié)果來看, 當前線程打印完畢之后將鎖進行釋放, 其他的線程才可以繼續(xù)打印. 線程打印的數(shù)據(jù)是分組打印, 因為當前線程已經(jīng)持有鎖, 但線程之間打印的順序是隨機的.

使用 Condition 實現(xiàn)等待/通知

關(guān)鍵字 synchronized 與 wait() 和 notify() / notifyall() 方法結(jié)合可以實現(xiàn)等待/通知模式, 只不過在使用時, 調(diào)用 notify() 方法 JVM 會隨機選擇一個 WAITNG 狀態(tài)的線程來執(zhí)行.

而使用 Condition 則可以更加靈活, 可以實現(xiàn) "選擇性通知", 可以指定的選擇喚醒哪些線程, 哪些線程繼續(xù)等待.

public class MyService {

    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();

    public void awaitA() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitA 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.await();

        System.out.println("end awaitA 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void awaitB() throws InterruptedException {
        lock.lock();

        System.out.println("begin awaitB 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.await();

        System.out.println("end awaitB 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        lock.unlock();
    }

    public void  signalAll_A() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_A 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionA.signalAll();

        lock.unlock();
    }

    public void  signalAll_B() throws InterruptedException {
        lock.lock();
        System.out.println("begin signalAll_B 時間" + System.currentTimeMillis() + "ThreadName=" + Thread.currentThread().getName());

        conditionB.signalAll();

        lock.unlock();
    }
}
public class ThreadA extends Thread {

    private MyService myService;
    public ThreadA(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitA();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class ThreadB extends Thread {

    private MyService myService;

    public ThreadB(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        try {
            myService.awaitB();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws IOException, InterruptedException {

        MyService myService = new MyService();

        ThreadA threadA = new ThreadA(myService);
        threadA.setName("a");
        threadA.start();

        ThreadB threadB = new ThreadB(myService);
        threadB.setName("b");
        threadB.start();

        Thread.sleep(3000);
        myService.signalAll_A();

    }
  • Object 類中的 wait() 方法相當于 Condition 類中的 await() 方法.
  • Object 類中的 wait(long timeout) 方法相當于 Condition 類中的 await(long time, TimeUnit unit) 方法.
  • Object 類中的 notify() 方法相當于 Condition 類中的 signal() 方法.
  • Object 類中的 notifyAll() 方法相當于 Condition 類中的 signalAll() 方法.

從執(zhí)行結(jié)果來看, a 和 b 線程被暫停, 當執(zhí)行 myService.signalAll_A() 方法時, a 線程繼續(xù)執(zhí)行, 而 b 線程仍然是等待狀態(tài).

常用方法

ReentrantLock 類

int getHoldCount() 查詢調(diào)用 lock() 方法的次數(shù).

final int getQueueLength() 估計等待鎖的線程數(shù). 比如有5個線程, 1個線程首先執(zhí)行 await() 方法, 那么在調(diào)用此方法后返回值是4, 說明有4個線程同時在等待lock的釋放.

int getWaitQueueLength(Condition condition) 返回與此鎖相關(guān)聯(lián)給定條件等待的線程數(shù)的估計. 比如有5個線程, 每個線程都執(zhí)行了同一個 condition 對象的 await() 方法, 則調(diào)用此方法時返回的值是5.

final boolean hasQueuedThreads() 判斷是否有線程等待此鎖.

final boolean hasQueuedThread(Thread thread) 判斷指定線程是否等待獲取此鎖.

boolean hasWaiters(Condition condition) 判斷線程有沒有調(diào)用 await() 方法.

void lockInterruptibly() throws InterruptedException 獲取鎖, 除非當前線程為interrupted.

Condition 類

void awaitUninterruptibly() 和 await() 區(qū)別就是當調(diào)用 interrupt() 方法時不會拋出 InterrputedException 異常.

以上是java中ReentrantLock類如何使用的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI