Java多執行緒生產者與消費者等待喚醒機制(示例)
阿新 • • 發佈:2018-12-24
在下面新建的兩條執行緒,兩條執行緒操作的物件都是學生類,一條執行緒生產學生物件的資料,一條執行緒消費學生物件的資料,且做到,有資料才消費,沒資料就等待,沒資料就生產,有資料就等待。
第一個案例是學生類物件,非常的簡單就定義了兩個成員變數,以及一個用於喚醒執行緒的標記。
成員變數預設會賦值,生命週期隨著物件的產生而產生,隨著物件的銷燬而銷燬,成員變數儲存在堆中
靜態變數就是類變數,隨著類的產生而產生,隨著類的銷燬而銷燬
區域性變數,方法體,或引數,隨著方法產生或銷燬,分配在棧記憶體中
public class Student { public String name; public int age; boolean flag; //預設情況是false--->沒有資料,如果是true說明有資料。 }
下面的是生產者學生物件的demo
在構造方法中傳遞了學生物件,保證生產者與消費者操作的是同一個物件。
wait:釋放資源,釋放鎖,object的方法,用在同步鎖中,以鎖控制執行緒
wait(),notify(),notifyAll()方法是用在同步當中的:必須是同步當中的同一把鎖操作執行緒。
package secondDemo; /** * Created by df on 2018/8/16. */ public class setThread implements Runnable { private Student s; int x = 0; public setThread(Student s) { this.s = s; } @Override public void run() { while (true) { synchronized (s) { //喚醒機制,生產者,先判斷有沒有資料,有資料等待消費,沒資料就生產資料 if (s.flag) { try { s.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //flag為false 執行以下程式碼 if (x % 2 == 0) { s.name = "java"; s.age = 25; } else { s.name = "android"; s.age = 20; } x++; //資料生產一次 修改標記為true,有了資料生產資料的執行緒就等待 s.flag=true; //喚醒執行緒 s.notify(); } } } }
下面的是學生物件的消費者模式demo
在構造方法中傳遞了學生物件,保證生產者與消費者操作的是同一個物件。
package secondDemo; /** * Created by df on 2018/8/16. */ public class getThread implements Runnable { private Student s; public getThread(Student s) { this.s = s; } @Override public void run() { while (true) { synchronized (s) { //消費者 有資料就消費,沒資料就等待資料被生產 if (!s.flag) { try { s.wait();//在等待的時候立即釋放鎖,方便其他的執行緒使用鎖。而且被喚醒時,就在此處喚醒, } catch (InterruptedException e) { e.printStackTrace(); } } // flag--->true:消費資料 System.out.println(s.name + " ==== " + s.age); // 消費完畢後,資料沒有了,修改標記 s.flag = false; // 喚醒執行緒 //喚醒並不代表你立即可以得到執行權,此時仍然需要搶CPU的執行權, s.notify(); } } } }
下面的是測試用例,就是簡單的建立了兩條執行緒,然後啟動剛才的生產者與消費者
public static void main(String[] args) {
// 共享資料,外界建立,作為引數,通過構造共有
Student s=new Student();
// 在構造中使用同一個引數
setThread st=new setThread(s);
getThread gt=new getThread(s);
Thread t1=new Thread(st);// 設定資料
Thread t2=new Thread(gt);// 獲取資料
t1.start();
t2.start();
}
最後就是執行完畢的結果