1. 程式人生 > 其它 >java中執行緒的知識08---利用Reentrantlock實現執行緒的等待和喚醒

java中執行緒的知識08---利用Reentrantlock實現執行緒的等待和喚醒

技術標籤:Java執行緒

我在《java中執行緒的知識05》中寫過執行緒的等待和喚醒,關鍵字synchronized與wait/notify或notifyAll方法想結合可以實現等待/通知模式,類RentrantLock也可以實現同樣的功能,但需要藉助Condition物件。Condition類是在JDK5中出現的技術,使用它有更好的靈活性,比如可以實現多路通知功能,也就是在一個Lock物件裡面可以建立多個Condition例項,執行緒物件可以註冊在指定的Condition中,從而可以有選擇性地進行執行緒通知,在除錯執行緒上更加靈活。

在使用notify/notifyAll方法進行通知時,被通知執行緒是由JVM隨機選擇的,但使用ReentrantLock結合Condition類可以實現選擇性通知,這個功能是非常重要的,而且在Condition在中是預設提供的。

而synchronized就相當於整個Lock物件中只有一個單一Condition物件,所有的執行緒都是註冊在它一個物件的身上。執行緒開始notifyAll時需要通知所有正在等待的執行緒,沒有選擇權,會出現相當大效率問題。

簡單寫,直接上程式碼:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo003 {
    public static void main(String[] args) throws InterruptedException {
        Demo03Service service = new Demo03Service();
        Thread t = new Demo003Thread(service);
        t.start();
        Thread.sleep(5000);
        service.signal();
    }
}

class Demo03Service {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void await(){
        try {
            lock.lock();
            System.out.println("await方法開始時間" + System.currentTimeMillis());
            condition.await();  // 需要在同步程式碼中呼叫,否則會丟擲IllegalMonitorStateException
            System.out.println("await方法結束時間" + System.currentTimeMillis());
            lock.unlock();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public void signal(){
        lock.lock();
        System.out.println("signal方法開始於" + System.currentTimeMillis());
        condition.signal();
        lock.unlock();
    }
}
class Demo003Thread extends Thread{
    private Demo03Service service;
    public Demo003Thread(Demo03Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.await();
    }
}

執行結果為:

await方法開始時間1611974288753
signal方法開始於1611974293759
await方法結束時間1611974293759

Process finished with exit code 0

一個簡單的執行緒的等待和喚醒功能就實現了。