Java高并发编程之Lock和Condition

前一篇文章,使用synchronized和wait、notify/notifyAll结合解决经典的生产者和消费者面试题,详见:Java高并发编程之经典面试题:生产者与消费者线程
这并不是唯一的解决方案,还有更好的,本篇文章讲解如何使用Lock和Condition来实现。
notify/notifyAll的缺陷在于不能指定哪些线程被唤醒,notifyAll的时候,wait状态的生产者和消费者统统被唤醒,而Condition则可以精确指定哪些线程被唤醒。
Condition是条件的意思,就是“在什么条件下做什么事”,Condition提供了两个方法,await和singalAll,功能类似于wait和notifyAll。
代码如下:

public class MyContainer2<T> {
    final private LinkedList<T> lists = new LinkedList<>();
    /**
     * 容器固定容量为10
     */
    final private int MAX = 10;
    /**
     * 容器初始元素个数为0
     */
    private int count = 0;

    private Lock lock = new ReentrantLock();
    private Condition producerCondition = lock.newCondition();
    private Condition consumerCondition = lock.newCondition();

    /**
     * put方法
     * @param t
     */
    public void put(T t) {
        lock.lock();
        try {
            while (MAX == lists.size()) {
                //是生产者就要等待
                producerCondition.await();
            }
            lists.add(t);
            ++count;
            System.out.println(Thread.currentThread().getName() + "进行生产了,当前剩余:" + getCount());
            //是消费者就要被唤醒
            consumerCondition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * get 方法
     * @return
     */
    public T get() {
        T t = null;
        lock.lock();
        try {
            while (0 == lists.size()) {
                //是消费者就要等待
                consumerCondition.await();
            }
            t = lists.removeLast();
            --count;

            System.out.println(Thread.currentThread().getName() + "进行消费了,当前剩余:" + getCount());

            //是生产者就要被唤醒
            producerCondition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return t;
    }

    /**
     * getCount方法
     * @return
     */
    public int getCount() {
        return this.count;
    }

    public static void main(String[] args) {
        MyContainer2<String> myContainer2 = new MyContainer2<>();
        //创建5个生产者线程
        for(int i = 1; i <= 5; i++) {
            new Thread(()->{
                while(true) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        myContainer2.put("");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "p_thread_" + i).start();
        }

        for(int i = 1; i <= 10; i++) {
            new Thread(()->{
                while(true) {
                    try {
                        TimeUnit.SECONDS.sleep(3);
                        myContainer2.get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "c_thread_" + i).start();
        }
    }
}

程序执行结果:

p_thread_1进行生产了,当前剩余:1
p_thread_5进行生产了,当前剩余:2
p_thread_4进行生产了,当前剩余:3
p_thread_2进行生产了,当前剩余:4
p_thread_3进行生产了,当前剩余:5
p_thread_1进行生产了,当前剩余:6
p_thread_5进行生产了,当前剩余:7
p_thread_3进行生产了,当前剩余:8
p_thread_4进行生产了,当前剩余:9
p_thread_2进行生产了,当前剩余:10
c_thread_2进行消费了,当前剩余:9
c_thread_1进行消费了,当前剩余:8
c_thread_5进行消费了,当前剩余:7
c_thread_3进行消费了,当前剩余:6
c_thread_4进行消费了,当前剩余:5
c_thread_6进行消费了,当前剩余:4
c_thread_9进行消费了,当前剩余:3
c_thread_7进行消费了,当前剩余:2
c_thread_8进行消费了,当前剩余:1
p_thread_1进行生产了,当前剩余:2
p_thread_3进行生产了,当前剩余:3
p_thread_2进行生产了,当前剩余:4
p_thread_5进行生产了,当前剩余:5
p_thread_4进行生产了,当前剩余:6
c_thread_10进行消费了,当前剩余:5
...
...

猜你喜欢

转载自blog.csdn.net/weixin_42486373/article/details/84067920
今日推荐