使用執行緒模擬企業的生產者和消費者
阿新 • • 發佈:2018-11-01
測試類:
public class Test01 {
public static void main(String[] args) {
MyStorage storage = new MyStorage();
Producer producer = new Producer(storage);
Consumer consumer = new Consumer(storage);
producer.setName("生產者");
consumer.setName("銷售人員");
producer.start();
consumer.start();
}
}
/**
- 倉庫類
- @author Administrator
*/
import java.util.LinkedList;
public class MyStorage {
LinkedList list = new LinkedList<>(); //儲存產品
private static final int MAX_CAPACITY = 100; //倉庫的最大容量
//儲存產品 ,約定每次存10個產品 public synchronized void store() { //倉庫已滿 ,生產者等待,等到消費者消費了後再繼續生產 while ( list.size() >= MAX_CAPACITY) { try { this.wait(); //wait()/notify()只能在同步程式碼塊中由鎖物件呼叫 //執行wait(),執行緒等待,會釋放鎖物件, } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println( Thread.currentThread().getName() + "儲存產品 前, 倉庫容量:" + list.size()); for( int i =1; i <= 10;i++){ //offer屬於 offer in interface Deque<E>,add 屬於 add in interface Collection<E>。 //當佇列為空時候,使用add方法會報錯,而offer方法會返回false。都是新增 //作為List使用時,一般採用add / get方法來 壓入/獲取物件。 //作為Queue使用時,才會採用 offer/poll/take等方法作為連結串列物件時,offer等方法相對來說沒有什麼意義這些方法是用於支援佇列應用的。 list.offer(new Object()); } System.out.println( Thread.currentThread().getName() + "存了10個產品後, 倉庫容量:" + list.size()); //通知消費者消費 this.notify(); } //取產品 , 約定一次取10個 public synchronized void get() { //判斷倉庫如果已空, 消費者需要等待, 等待生產者生產了產品後再繼續消費 while ( list.size() <= 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println( Thread.currentThread().getName() + "消費 前, 倉庫容量:" + list.size()); for( int i =1; i <= 10;i++){ //poll是減少的意思 list.poll(); } System.out.println( Thread.currentThread().getName() + "消費了10個產品 後, 倉庫容量:" + list.size()); //通知生產者生產 this.notifyAll(); /*notify和notifyAll的區別 如果執行緒呼叫了物件的 wait()方法,那麼執行緒便會處於該物件的等待池中,等待池中的執行緒不會去競爭該物件的鎖。 當有執行緒呼叫了物件的 notifyAll()方法(喚醒所有 wait 執行緒)或 notify()方法(只隨機喚醒一個 wait 執行緒),被喚醒的的執行緒便會進入該物件的鎖池中,鎖池中的執行緒會去競爭該物件鎖。也就是說,呼叫了notify後只要一個執行緒會由等待池進入鎖池,而notifyAll會將該物件等待池內的所有執行緒移動到鎖池中,等待鎖競爭 優先順序高的執行緒競爭到物件鎖的概率大,假若某執行緒沒有競爭到該物件鎖,它還會留在鎖池中,唯有執行緒再次呼叫 wait()方法,它才會重新回到等待池中。而競爭到物件鎖的執行緒則繼續往下執行,直到執行完了 synchronized 程式碼塊,它會釋放掉該物件鎖,這時鎖池中的執行緒會繼續競爭該物件鎖。 */ }
}
/**
- 生產者執行緒
- @author Administrator
*/
public class Producer extends Thread {
MyStorage storage;
public Producer(MyStorage storage) {
super();
this.storage = storage;
}
@Override
public void run() {
//
for(int d = 1; d <= 200; d++){
storage.store();
}
}
}
/**
- 消費者執行緒
- @author Administrator
*/
public class Consumer extends Thread {
MyStorage storage;
public Consumer(MyStorage storage) {
super();
this.storage = storage;
}
@Override
public void run() {
//
for(int d = 1; d <= 200; d++){
storage.get();
}
}
}