線程交互
有時線程之間有交互通知的需求,例如生產者消費者問題。生產者每次生產一個商品,消費者每次消耗一個商品;當商品數目爲0的時候,消費者線程需要等待生產者生產出商品,才能繼續運行;當商品數目達到上限時,生產者線程需要等待消費者消耗了商品。纔可以繼續運行。
在操作系統中,上述思想採用的是信號量機制以及PV操作,對應Java中的wait() 和 notify() 方法:
wait() :讓當前佔用了某個對象的線程,暫時進入等待狀態,並釋放掉當前的佔用。等待其他進程的notify() 將它喚醒。注意,wait() 方法只能使用在synchronized塊中。
notify() :通知一個等待在當前同步對象上的線程,告訴他可以醒了,並有機會佔用當前對象。
notifyAll() :通知所有等待當前同步對象的上的線程,告訴他們可以醒了,並有機會佔用當前對象。
生產者消費者問題
首先看一段代碼:
class Store {
final int capacity = 8; //item容量爲8
int item; //當前商品個數
public Store(int item) {
this.item = item;
}
//生產者方法,每次生產一個item
public synchronized void produce() {
//如果倉庫滿了,則wait(),等待消費者消費
if(item == capacity) {
try {
this.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
item += 1;
//生產者生產了商品,告訴消費者你們可以消費了
this.notify();
System.out.println("生產後的量爲:" + this.item);
}
//消費者方法,每次消耗一個item
public synchronized void consume() {
//商品爲空的時候,消費者開始等待
if(item == 0) {
try {
this.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
item -= 1;
//消費者通知生產者,你們可以繼續生產了
this.notify();
System.out.println("消費後的量爲:" + this.item);
}
}
注意,wait()方法和notify()方法並不是線程類Thread的方法,而是超類Object中的方法。因此所有的Object都可以被用作同步對象。因此準確來說,wait()和notify()是同步對象的方法。