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

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

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

这是一个典型的多线程面试题,考验对锁和多线程对运用。要想实现,有两种常见模式。一种是通过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();
    }
}
相关文章
|
5月前
|
容器
多线程学习之生产者和消费者与阻塞队列的关系
多线程学习之生产者和消费者与阻塞队列的关系
22 0
|
5月前
|
消息中间件 Java 测试技术
Java多线程消费消息
关键词:Java,多线程,消息队列,rocketmq 多线程一个用例之一就是消息的快速消费,比如我们有一个消息队列我们希望以更快的速度消费消息,假如我们用的是rocketmq,我们从中获取消息,然后使用多线程处理。
68 0
|
3月前
|
缓存 C语言
C语言生产者与消费者问题
C语言生产者与消费者问题
21 0
|
3月前
|
Java
用java实现生产者和消费者模式
用java实现生产者和消费者模式
29 1
|
8月前
经典例题:生产者/消费者
经典例题:生产者/消费者
15 0
OS中经典问题之消费者-生产者同步问题
OS中经典问题之消费者-生产者同步问题
|
消息中间件 缓存 算法
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
209 0
阿里二面:RocketMQ 消息积压了,增加消费者有用吗?
|
设计模式 安全
生产者与消费者模型
生产者与消费者模型
71 0
生产者与消费者模型
|
存储 算法
生产者与消费者模型:餐厅吃饭问题
生产者与消费者模型:餐厅吃饭问题
78 0
|
安全 Java
Java多线程——生产者/消费者问题
生产者/消费者问题
144 0