多线程面试题系列3_生产者消费者模式的两种实现方法

题目

生产者-消费者模式
题目:
写一个固定容量的同步容器,拥有put和get方法,以及getCount方法
能够支持2个生产者线程和10个消费者线程的阻塞调用

  • 解法一:

    使用wait和notify/notifyAll实现

    需要注意的点:
    因为一个生产者只能生产一个食物,所以要想满足所有消费者必须启用数量相等的生产者线程。
    wait()方法必须由一个上锁的对象使用。
    使用notifyALL()。
    使用while配合wait()。

class Container {
    private static final int SIZE = 10;
    volatile static int count = 0;
    Object o = new Object();
    void put() {
        synchronized(o) {
            while (getCount() == SIZE) {
                try {
                    o.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            count++;
            System.out.println("Producer now!	" + "AFTER ALL: " + getCount());
            o.notifyAll();
        }
    }
    void get() {
        synchronized(o) {
            while (getCount() == 0) {
                try {
                    o.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            count--;
            System.out.println("Consumer now!	" + "AFTER ALL: " + getCount());
            o.notifyAll();
        }
    }
    int getCount() {
        return count;
    }
}
public class Question3 {
    public static void main(String[] args) {
        Container container = new Container();
        for(int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    container.get();
                }
            });
            thread.start();
        }
        try {
            Thread.sleep(2000);
        } catch(Exception e) {
            e.printStackTrace();
        }
        for(int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    container.put();
                }
            });
            thread.start();
        }
    }
}
  • 解法二:

使用wait和notify/notifyAll实现

需要注意的点:
因为一个生产者只能生产一个食物,所以要想满足所有消费者必须启用数量相等的生产者线程。
await()方法必须由一个上锁的ReentrantLock对象使用。
使用while配合await()。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Container1 {
    volatile static int count = 0;
    private static final int SIZE = 10;
    ReentrantLock lock = new ReentrantLock();
    Condition condition_get = lock.newCondition();
    Condition condition_put = lock.newCondition();
    void get() {
        lock.lock();
        while(getCount() == 0) {
            try {
                condition_get.await();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        count--;
        System.out.println("Consumer now!	" + "AFTER ALL: " + getCount());
        condition_put.signalAll();
        lock.unlock();
    }
    void put() {
        lock.lock();
        while(getCount() == SIZE) {
            try {
                condition_put.await();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        count++;
        System.out.println("Producer now!	" + "AFTER ALL: " + getCount());
        condition_get.signalAll();
        lock.unlock();
    }
    int getCount() {
        return count;
    }
}
public class Question3a {
    public static void main(String[] args) {
        Container1 container1 = new Container1();
        for(int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    container1.get();
                }
            });
            thread.start();
        }
        try {
            Thread.sleep(2000);
        } catch(Exception e) {
            e.printStackTrace();
        }
        for(int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    container1.put();
                }
            });
            thread.start();
        }
    }
}

原文地址:https://www.cnblogs.com/fromneptune/p/11794216.html