91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

java線程等待喚醒機制

發布時間:2021-09-09 10:07:45 來源:億速云 閱讀:143 作者:chen 欄目:編程語言

這篇文章主要講解了“java線程等待喚醒機制”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“java線程等待喚醒機制”吧!

1)3種讓線程等待和喚醒的方法

方式1:使用Object中的wait()方法讓線程等待,使用Object中的notify()方法喚醒線程

1、wait()、notify/notifyAll() 方法是Object的本地final方法,無法被重寫。

2、wait()使當前線程阻塞,前提是 必須先獲得鎖,一般配合synchronized 關鍵字使用,即,一般在synchronized 同步代碼塊里使用 wait()、notify/notifyAll() 方法。

3、 由于 wait()、notify/notifyAll() 在synchronized 代碼塊執行,說明當前線程一定是獲取了鎖的。

當線程執行wait()方法時候,會釋放當前的鎖,然后讓出CPU,進入等待狀態。

只有當 notify/notifyAll() 被執行時候,才會喚醒一個或多個正處于等待狀態的線程,然后繼續往下執行,直到執行完synchronized 代碼塊的代碼或是中途遇到wait() ,再次釋放鎖。

也就是說,notify/notifyAll() 的執行只是喚醒沉睡的線程,而不會立即釋放鎖,鎖的釋放要看代碼塊的具體執行情況。所以在編程中,盡量在使用了notify/notifyAll() 后立即退出臨界區,以喚醒其他線程讓其獲得鎖

4、wait() 需要被try catch包圍,以便發生異常中斷也可以使wait等待的線程喚醒。

5、notify 和wait 的順序不能錯,如果A線程先執行notify方法,B線程在執行wait方法,那么B線程是無法被喚醒的。

6、notify 和 notifyAll的區別

notify方法只喚醒一個等待(對象的)線程并使該線程開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決于操作系統對多線程管理的實現。notifyAll 會喚醒所有等待(對象的)線程,盡管哪一個線程將會第一個處理取決于操作系統的實現。如果當前情況下有多個線程需要被喚醒,推薦使用notifyAll 方法。比如在生產者-消費者里面的使用,每次都需要喚醒所有的消費者或是生產者,以判斷程序是否可以繼續往下執行。

7、在多線程中要測試某個條件的變化,使用if 還是while?

  要注意,notify喚醒沉睡的線程后,線程會接著上次的執行繼續往下執行。所以在進行條件判斷時候,可以先把 wait 語句忽略不計來進行考慮;顯然,要確保程序一定要執行,并且要保證程序直到滿足一定的條件再執行,要使用while進行等待,直到滿足條件才繼續往下執行

package com.lyy.juc;import java.util.concurrent.TimeUnit;public class LockSupportDemo {public static void main(String[] args)//main方法,主線程一切程序入口    {Object objectLock = new Object(); //同一把鎖,類似資源類        new Thread(() -> {synchronized (objectLock) {try {objectLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }System.out.println(Thread.currentThread().getName() + "\t" + "被喚醒了");
        }, "t1").start();//暫停幾秒鐘線程        try {TimeUnit.SECONDS.sleep(3L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }new Thread(() -> {synchronized (objectLock) {objectLock.notify();
            }//objectLock.notify();            /*synchronized (objectLock) {                try {                    objectLock.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }*/        }, "t2").start();


    }
}

三秒后打印

t1    被喚醒了

java線程等待喚醒機制

方式2:使用JUC包中Condition的await()方法讓線程等待,使用signal()方法喚醒線程

package com.lyy.juc;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class LockSupportDemo2 {public static void main(String[] args) {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + "\t" + "start");condition.await();System.out.println(Thread.currentThread().getName() + "\t" + "被喚醒");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {lock.unlock();
            }
        }, "t1").start();//暫停幾秒鐘線程        try {TimeUnit.SECONDS.sleep(3L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }new Thread(() -> {lock.lock();try {condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {lock.unlock();
            }System.out.println(Thread.currentThread().getName() + "\t" + "通知了");
        }, "t2").start();

    }
}

java線程等待喚醒機制

t1 線程在前,先執行start 然后,main執行睡三秒,t2執行start ,先執行await方法,后執行signal ,所以先打印t1 被喚醒,t2 被通知在后

但我把順序換一下,打印結果順序就不一樣了

package com.lyy.juc;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class LockSupportDemo2 {public static void main(String[] args) {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();//暫停幾秒鐘線程        try {TimeUnit.SECONDS.sleep(3L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + "\t" + "start");condition.await();System.out.println(Thread.currentThread().getName() + "\t" + "被喚醒");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {lock.unlock();
            }
        }, "t1").start();new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + "\t" + "start");condition.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {lock.unlock();
            }System.out.println(Thread.currentThread().getName() + "\t" + "通知了");
        }, "t2").start();

    }
}

java線程等待喚醒機制

Object和Condition使用的限制條件

線程先要獲得并持有鎖,必須在鎖塊(synchronized或lock)中

方式3:LockSupport類可以阻塞park當前線程以及喚醒unpark指定被阻塞的線程

通過park()和unpark(thread)方法來實現阻塞和喚醒線程的操作

LockSupport是用來創建鎖和其他同步類的基本線程阻塞原語。
 
LockSupport類使用了一種名為Permit(許可)的概念來做到阻塞和喚醒線程的功能, 每個線程都有一個許可(permit),
permit只有兩個值1和零,默認是零。
可以把許可看成是一種(0,1)信號量(Semaphore),但與 Semaphore 不同的是,許可的累加上限是1。

park() /park(Object blocker)

不傳阻塞當前線程/傳阻塞傳入的具體線程

unpark(Thread thread) 必須指定要喚醒的線程 

package com.lyy.juc;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.LockSupport;public class LockSupportDemo3 {public static void main(String[] args) {//正常使用+不需要鎖塊        Thread t1 = new Thread(() -> {System.out.println(Thread.currentThread().getName() + " " + "1111111111111");LockSupport.park();System.out.println(Thread.currentThread().getName() + " " + "2222222222222------end被喚醒");
        }, "t1");t1.start();//暫停幾秒鐘線程        try {TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName() + "   -----LockSupport.unparrk() invoked over");

    }
}

java線程等待喚醒機制

permit默認是零,所以一開始調用park()方法,當前線程就會阻塞,直到別的線程將當前線程的permit設置為1時,park方法會被喚醒,
然后會將permit再次設置為零并返回。
 

java線程等待喚醒機制
調用unpark(thread)方法后,就會將thread線程的許可permit設置成1(注意多次調用unpark方法,不會累加,permit值還是1)會自動喚醒thread線程,即之前阻塞中的LockSupport.park()方法會立即返回。

java線程等待喚醒機制

感謝各位的閱讀,以上就是“java線程等待喚醒機制”的內容了,經過本文的學習后,相信大家對java線程等待喚醒機制這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

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

AI

余江县| 辽源市| 鸡西市| 河津市| 唐海县| 迁西县| 和政县| 伊川县| 霍山县| 外汇| 舟山市| 翁牛特旗| 合作市| 栾川县| 绥江县| 离岛区| 蓬莱市| 水城县| 涞水县| 嘉兴市| 攀枝花市| 宽甸| 昌都县| 广西| 麻阳| 那曲县| 万州区| 琼海市| 偃师市| 锡林浩特市| 宝山区| 开原市| 子长县| 夏津县| 鄂尔多斯市| 溧阳市| 达日县| 怀宁县| 彭水| 聊城市| 拜泉县|