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

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

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

这是一个典型的多线程面试题,考验对锁和多线程对运用。要想实现,有两种常见模式。一种是通过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();
    }
}
相关文章
|
安全 算法 编译器
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
363 2
|
2月前
|
机器学习/深度学习 传感器 算法
【2024最新优化算法】青蒿素优化算法与霜冰优化算法RIME对比(Matlab代码实现)
【2024最新优化算法】青蒿素优化算法与霜冰优化算法RIME对比(Matlab代码实现)
150 1
|
Java 项目管理 Maven
这你必须知道,如何上传自己的jar包到maven公共远程中央仓库
这你必须知道,如何上传自己的jar包到maven公共远程中央仓库
1323 0
|
监控 调度 Android开发
看完这篇 Android ANR 分析,就可以和面试官装逼了!
ANR概述 首先,ANR(Application Not responding)是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。
8447 0
|
UED 开发者
鸿蒙next版开发:ArkTS组件通用属性(多态样式)
在HarmonyOS 5.0中,ArkTS的多态样式(stateStyles)功能允许开发者根据不同状态(如正常、按压、禁用、聚焦、选中等)为组件设置不同的样式,从而提供更丰富的用户体验。通过stateStyles属性,可以动态改变组件样式,提升用户交互的直观性和界面美观性。示例代码展示了如何为文本组件设置正常和按压状态的样式。
618 1
|
SQL 分布式计算 并行计算
PostgreSQL 并行计算解说 之1 - parallel seq scan
标签 PostgreSQL , cpu 并行 , smp 并行 , 并行计算 , gpu 并行 , 并行过程支持 背景 PostgreSQL 11 优化器已经支持了非常多场合的并行。简单估计,已支持27余种场景的并行计算。 parallel seq scan parallel index scan parallel index only scan
5236 0
|
机器学习/深度学习 运维 算法
深入探索机器学习中的支持向量机(SVM)算法:原理、应用与Python代码示例全面解析
【8月更文挑战第6天】在机器学习领域,支持向量机(SVM)犹如璀璨明珠。它是一种强大的监督学习算法,在分类、回归及异常检测中表现出色。SVM通过在高维空间寻找最大间隔超平面来分隔不同类别的数据,提升模型泛化能力。为处理非线性问题,引入了核函数将数据映射到高维空间。SVM在文本分类、图像识别等多个领域有广泛应用,展现出高度灵活性和适应性。
584 2
|
前端开发 计算机视觉
提升编程效率的利器: 解析Google Guava库之集合篇RangeMap范围映射(六)
提升编程效率的利器: 解析Google Guava库之集合篇RangeMap范围映射(六)
|
算法 Java Python
用友Java后端笔试2023-8-5
用友Java后端笔试2023-8-5
221 0
用友Java后端笔试2023-8-5