【線程間通信:等待喚醒機制】
阿新 • • 發佈:2018-09-02
runnable lean ride system not 必須 this 消費者 clas
在線程安全解決之後,還是一樣存在著如下的問題:
A:如果消費者先搶到CPU的執行權,就會去消費數據,但是現在的數據是默認值,沒有意義,應該等著數據有意義,再消費。
B:如果生產者先搶到CPU的執行權,就會去生產數據,但是呢,它生產完數據後,還繼續擁有執行權,它又繼續產生數據。這是有問題的,它應該等著消費者把數據消費掉,然後再生產。
正常的思路:
A:生產者:先看是否有數據,有就等待,沒有就生產,生產完後通知消費者來消費數據。
B:消費者:先是是否有數據,有就消費,沒有就等待,通知生產者生產數據。
為了處理這樣的問題,JAVA就提供了一種機制,等待喚醒機制。
等待喚醒: Object 類中提供了三個方法:
wait():等待
notify():喚醒單個線程
notifyAll():喚醒所有線程
為什麽這些方法不定義在Thread類中呢?
這些方法的調用必須通過鎖對象調用,要所有鎖對象都可以調用的話,方法就應該在他們共有的父類上,也就是Object類。
例子:線程間通信:生產者消費者(等待喚醒機制)
package com.test; public class Student { String name; int age; boolean isTrue; public synchronized void set(String name, intage) { /**如果有數據,就等待*/ if (this.isTrue) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } /**設置數據*/ this.name = name; this.age = age; /**修改標記*/ this.isTrue = true; this.notify(); } public synchronized void get() { /**如果沒有數據,就等待*/ if (!this.isTrue) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } /**獲取數據*/ System.out.println(this.name + "---" + this.age); /**修改標記*/ this.isTrue = false; this.notify(); } }
package com.test; public class SetThread implements Runnable { private Student s; private int x = 0; public SetThread(Student s) { this.s = s; } @Override public void run() { while (true) { if (x % 2 == 0) { s.set("葉胖子", 27); } else { s.set("王瘦子", 31); } x++; } } }
package com.test; public class GetThread implements Runnable { private Student s; public GetThread(Student s){ this.s = s; } @Override public void run() { while (true){ s.get(); } } }
package com.test; public class StudentTest { 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(); } }
【線程間通信:等待喚醒機制】