生產者消費者問題

首先用一個普通的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

相關文章
相關標籤/搜索