java中執行緒的知識08---利用Reentrantlock實現執行緒的等待和喚醒
阿新 • • 發佈:2021-01-31
技術標籤: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
一個簡單的執行緒的等待和喚醒功能就實現了。