首先用一個普通的stack來實現消費者和生產者。java
package concurrent; import java.util.Stack; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class StackPC { class MyStack{ private Stack stack = new Stack(); private int size = 0; public synchronized void push(int i ){ stack.push(i); size = size +1; } public synchronized int pop(){ int i = (int) stack.pop(); size = size -1; return i; } public boolean isEmpty(){ return stack.isEmpty(); } public int size(){ return size; } } class Producer{ private MyStack mystack ; public Producer(MyStack mystack){ this.mystack = mystack; } public void producer(){ try { synchronized (mystack){ if(mystack.size()>10) mystack.wait(); int i = (int) Math.round((Math.random()*100)); mystack.push(i); System.out.println("生產了"+i+"此時size爲"+mystack.size()); mystack.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Customer{ private MyStack mystack ; public Customer(MyStack mystack){ this.mystack = mystack; } public void customer(){ try { synchronized(mystack){ if(mystack.isEmpty()) mystack.wait(); int i = mystack.pop(); System.out.println("消費了"+i+"此時size爲"+mystack.size); mystack.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { StackPC test = new StackPC(); StackPC.MyStack stack = test.new MyStack(); final StackPC.Producer p = test.new Producer(stack); final StackPC.Customer c = test.new Customer(stack); Runnable pRunner = new Runnable() { @Override public void run() { while(true){ p.producer(); } } }; Runnable cRunner = new Runnable() { @Override public void run() { while(true){ c.customer(); } } }; ExecutorService exe = Executors.newCachedThreadPool(); exe.execute(pRunner); exe.execute(cRunner); } }
運行結果以下:緩存
生產者最多生產到size爲11的時候就會喚醒消費者進行消費,消費者消費到size爲0時會喚醒生產者進行生產。當stack的容量大於0小於11時,生產和消費是並行運行的。這裏因爲cpu執行較快沒有明顯的生產消費交替進行,而是一次消費或者生產多個而後才交替執行。dom
上面是咱們本身使用stack來對產品進行緩存,其實java中已經有很是完善的類提供給咱們使用,使用阻塞隊列來模擬生產者消費者問題實現更爲簡單。ide
package concurrent; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class BlockingQueueTest { public static void main(String[] args) throws InterruptedException { final BlockingQueue bq = new ArrayBlockingQueue(10); Runnable producer = new Runnable() { @Override public void run() { int i = 0; while(true){ try { i++; bq.put(i); System.out.println("生產了一個"+ i); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); break; } } } }; Runnable customer = new Runnable() { @Override public void run() { while(true){ try { System.out.println("消費了一個"+bq.take()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); break; } } } }; ExecutorService exe = Executors.newCachedThreadPool(); exe.execute(producer); exe.execute(customer); // Thread.sleep(1000); // exe.shutdownNow(); } }
這裏咱們不須要再手動寫wait和notify,也不用對隊列進行手動加鎖,這裏生產者生產的速度快與消費者,因此在開始的時候雖然是並行執行,可是生產者的速度較快,阻塞隊列很快達到容量最大值10,這時候生產者沒法繼續生產,阻塞等待,當消費者消費後,容量減少,生產者繼續生產。this
能夠看出在容量到達10 之後,消費者消費一個生產者才繼續生產一個,使用阻塞隊列可有效平衡生產者和消費者。spa