笔试题:请写出一个消费者生产者模型

简介: “请写出一个生产者消费者模型。一个生产者,一个消费者,生产者生产一个,消费者消费一个”。

“请写出一个生产者消费者模型。一个生产者,一个消费者,生产者生产一个,消费者消费一个”。

这是一个典型的多线程面试题,考验对锁和多线程对运用。要想实现,有两种常见模式。一种是通过wait() / notify(),另一种是通过 ReentrantLock 的 condition。

wait()和notify()实现

Object的wait() / notify()是第一种实现方式。

这里有必要提一下Thread.sleep()和Object.wait()的区别。

sleep和wait区别

1、Thread.sleep()不会导致锁行为的改变,如果当前线程是拥有锁的,那么Thread.sleep()不会让线程释放锁。如果能够帮助你记忆的话,可以简单认为和锁相关的方法都定义在Object类中,因此调用Thread.sleep()是不会影响锁的相关行为。

2、Thread.sleep和Object.wait都会暂停当前的线程,对于CPU资源来说,不管是哪种方式暂停的线程,都表示它暂时不再需要CPU的执行时间。OS会将执行时间分配给其它线程。区别是调用wait后,需要别的线程执行notify/notifyAll才能够重新获得CPU执行时间。

wait和notify

wait():放弃锁,使自己处于等待状态,让其他线程执行。

notify():向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。

实现代码如下:

public class Demo {
    static volatile int i = 0;
    static final Object LOCK = new Object();

    public static void add() throws InterruptedException {
        synchronized (LOCK) {
            while (i == 0) {
                System.out.print("add\t");
                System.out.println(++i);
                LOCK.notify();
                LOCK.wait();
            }
        }
    }


    public static void sub() throws InterruptedException {
        synchronized (LOCK) {
            while (i == 1) {
                System.out.print("sub\t");
                System.out.println(--i);
                LOCK.notify();
                LOCK.wait();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    add();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    sub();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

signal()和await()实现

ReentrantLock的signal() / await()是第二种实现方式。利用的是 ReentrantLock 内部的同步对列和条件队列来实现。这个原理需要可以在后面讲解。

public class Demo2 {
    static volatile int i = 0;
    static final ReentrantLock LOCK = new ReentrantLock();
    static final Condition condition = LOCK.newCondition();

    public static void add() throws InterruptedException {
        LOCK.lock();
        try {
            while (i == 0) {
                Thread.sleep(1000);
                System.out.print("add\t");
                System.out.println(++i);
                condition.signal();
                condition.await();
            }
        } finally {
            LOCK.unlock();
        }
    }


    public static void sub() throws InterruptedException {
        LOCK.lock();
        try {
            while (i == 1) {
                Thread.sleep(1000);
                System.out.print("sub\t");
                System.out.println(--i);
                condition.signal();
                condition.await();
            }
        } finally {
            LOCK.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            while (true) {
                try {
                    add();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(() -> {
            while (true) {
                try {
                    sub();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
相关文章
|
容器
多线程学习之生产者和消费者与阻塞队列的关系
多线程学习之生产者和消费者与阻塞队列的关系
61 0
|
消息中间件 Java 测试技术
Java多线程消费消息
关键词:Java,多线程,消息队列,rocketmq 多线程一个用例之一就是消息的快速消费,比如我们有一个消息队列我们希望以更快的速度消费消息,假如我们用的是rocketmq,我们从中获取消息,然后使用多线程处理。
130 0
|
3月前
|
消息中间件 NoSQL 关系型数据库
【多线程-从零开始-捌】阻塞队列,消费者生产者模型
【多线程-从零开始-捌】阻塞队列,消费者生产者模型
39 0
|
5月前
|
安全
LinkedBlockingQueue实现的生产者和消费者模型
LinkedBlockingQueue实现的生产者和消费者模型
44 1
经典例题:生产者/消费者
经典例题:生产者/消费者
40 0
|
消息中间件 缓存 算法
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
271 0
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
|
设计模式 安全
生产者与消费者模型
生产者与消费者模型
109 0
生产者与消费者模型
|
存储 算法
生产者与消费者模型:餐厅吃饭问题
生产者与消费者模型:餐厅吃饭问题
122 0
|
消息中间件 缓存 网络协议
带你涨姿势的认识一下Kafka之消费者
本篇文章是 《带你涨姿势的认识一下Kafka》系列第三篇文章,历史文章请戳
带你涨姿势的认识一下Kafka之消费者

热门文章

最新文章

下一篇
开通oss服务