典型的生產者消費者模式

下面是一個典型的生產者消費者模式寫法,註釋比較清晰,便於大家學習。


import HomeWork01.Container.Producer;

/**
 * 容器類,構建生產者和消費者兩個內部類,和put(),take()兩個方法;
 *@project Java_pro
 */
class Container {
    /**
     * size:容器容量;
     * array:構造的容器;
     * sth:放入容易的元素,每放入一次執行sth--;
     */
    private int size;
    private Object[] array;
    private volatile Integer sth = 100;

    /*構造方法傳遞容量參數*/
    public Container(int cap) {
        this.array = new Object[cap];
    }

    /**
     * tName:當前線程名稱
     * @param obj:放入容器的對象
     * 判斷容器容量是否已滿,如果滿了打印語句,執行wait()方法,阻塞調用此方法的線程,釋放鎖;
     * 否則在size位置放入obj,打印線程tName放入obj,並擴容;
     * 完成放入後廣播通知其他正在處於wait()的線程,允許取數據;
     */
    public synchronized void put(Object obj) {
        String tName = Thread.currentThread().getName();

        while (size == array.length) {
            System.out.println("容器已經滿了。");
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        array[size] = obj;
        System.out.println("Thread " + tName + " put: " + obj);
        size++;
        notifyAll();
    }

    /**
     * tName:當前線程名稱
     * 判斷容器容量是否已空,如果空了打印語句,執行wait()方法,阻塞調用此方法的線程,釋放鎖;
     * 否則取出首位元素,打印tName取出obj;
     * 取出後將1號至隊尾所有元素賦值到0號位至隊尾-1位,一共size-1個元素,size--;
     * 完成取出後廣播通知其他正在處於wait()的線程,允許放數據;
     */
    public synchronized void take() {
        String tName = Thread.currentThread().getName();
        while (size == 0) {
            System.out.println("容器已經空了。");
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        Object temp = array[0];
        System.out.println("Thread " + tName + " take:" + temp);
        System.arraycopy(array, 1, array, 0, size - 1);
        size--;
        array[size] = null;

        notifyAll();
    }

    /*生產者線程調用put()方法放入數據sth*/
    class Producer extends Thread {
        Container container;

        public Producer(Container container) {
            this.container = container;
        }

        @Override
        public void run() {
            while (true) {
                container.put(sth);
                --sth;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }

    /*消費者線程調用take()方法取出數據sth*/
    class Consumer extends Thread {
        Container container;
        Object temp;

        public Consumer(Container container) {
            this.container = container;
        }

        @Override
        public void run() {
            while (true) {
                container.take();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }

        }
    }
}

public class Producer_ConsumerDemo {
    public static void main(String[] args) throws InterruptedException {
        Container c = new Container(5);

        Producer pro1 = c.new Producer(c);
        pro1.start();
        c.new Consumer(c).start();

    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章