只有同步監聽對象才能夠調用 wait() 和 notify() 方法,不然報錯
線程之間進行通訊,且防止耦合度太高,使用一箇中間類做爲通訊的共同資源java
source 做爲兩個線程的參數傳入ide
public class TestDemo { public static void main(String[] args) { ShareSources source = new ShareSources(); new Producer(source).start(); new Comsumer(source).start(); } }
public class ShareSources { private String name; private String sex; private Boolean isEmpty = true;//使用一個參數做爲標誌 /** * 存入數據 * @param name * @param sex */ synchronized public void push(String name, String sex) {//同步方法,保證了該方法的原子性 try { //此處使用While比If更加合理, while (!isEmpty) {// 生產者是當前線程,若是資源任存在,則當前線程釋放鎖,進入等待池中,釋放後,消費者進程得到鎖 this.wait();//this 指的是 source 對象 進入等待池中的線程只能被其餘線程喚醒,這裏只能在消費者線程中喚醒 } //---------------------開始生產------------------------- this.name = name; Thread.sleep(10); this.sex = sex; //---------------------結束生產------------------------- isEmpty = false; this.notifyAll();//同時將其餘線程喚醒 } catch (Exception e) { e.printStackTrace(); } } /** * 獲取資源 */ synchronized public void get() { try { while (isEmpty) {//若是資源不存在 this.wait();//當前線程是消費者,進入等待池 } } catch (InterruptedException e) { e.printStackTrace(); } //---------------------開始消費------------------------- Thread.sleep(10); System.out.println(this.name + "-" + this.sex); //---------------------結束消費------------------------- isEmpty = true; this.notifyAll();//同時將其餘線程喚醒 } }
生產者可能存在多個,且須要與消費者不一樣線程測試
public class Producer extends Thread { private ShareSources source = null; public Producer(ShareSources source) {//經過構造器獲取相同的資源 this.source = source; } @Override public void run() { for (int i = 0; i < 50; i++) { if (i % 2 == 0) { source.push("春哥", "男"); }else { source.push("鳳姐", "女"); } } } }
public class Comsumer extends Thread { private ShareSources source = null; public Comsumer(ShareSources source) { this.source = source; } public void run() { for (int i = 0; i < 50; i++) { source.get(); } } }
須要注意的是,condition 的操做必定要在獲取鎖以後,釋放鎖以前執行,不然報錯this
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ShareSources { private String name; private String sex; private Boolean isEmpty = true; // 實例化鎖 private final Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition();// 因爲Condition是一個接口,lock.newCondition()方法返回一個綁定的Condition實例 /** * 存入數據 * * @param name * @param sex */ public void push(String name, String sex) { lock.lock(); try { if (!isEmpty) { condition.await();// 使用condition的await()方法至關於 Object 類的 wait 方法 } this.name = name; Thread.sleep(10); this.sex = sex; isEmpty = false; condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } /** * 獲取資源 */ public void get() { lock.lock(); try { if (isEmpty) { condition.await();// 使用condition的await()方法至關於 Object 類的 wait 方法 } Thread.sleep(10); System.out.println(this.name + "-" + this.sex); isEmpty = true; condition.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }