【JAVA高级面试题】运用锁机制实现一个自定义的阻塞队列

文章目录

前言

前几天看见一个高级Java面试题,我觉得很有代表意义。既考察了面试者的基本锁机制运用,也了解了阻塞队列的产生实现原理。先分享出来,以供鉴赏。

面试题:实现一个自定义的阻塞队列,它应该支持以下功能:

添加元素到队列末尾(如果队列已满,则阻塞添加线程直到有空间)

从队列头部移除元素(如果队列为空,则阻塞获取元素的线程直到有元素可消费)

查询队列是否为空

查询队列是否已满

要求使用Java的ReentrantLock和Condition类来实现线程间的同步。

实战演示

既然题目说到了使用Java的ReentrantLock和Condition类来实现线程间的同步,也就为我们指明了方向,直接可以按照题目的思路进行编码。当然,如果题目没有要求使用技术点,你是否知道还有哪些方式可以实现这个阻塞队列呢?

自定义阻塞队列编码如下:

bash 复制代码
/**
 * CustomBlockingQueue
 * @author senfel
 * @date 2024/2/21 12:50
 */
public class CustomBlockingQueue<T> {
    private final LinkedList<T> queue = new LinkedList<>();
    private final int capacity;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();
    private final Condition notFull = lock.newCondition();

    public CustomBlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    /**
     * put
     * @author senfel
     * @date 2024/2/21 12:52
     * @return void
     */
    public void put(T item) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                notFull.await();
            }
            if (queue.isEmpty()) {
                notEmpty.signal(); // 如果之前有等待的消费者,现在可以唤醒了
            }
            queue.addLast(item);
        } finally {
            lock.unlock();
        }
    }

    /**
     * take
     * @author senfel
     * @date 2024/2/21 12:59
     * @return void
     */
    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            if (queue.size() == capacity) {
                notFull.signal(); // 如果之前有等待的生产者,现在可以唤醒了
            }
            return queue.removeFirst();
        } finally {
            lock.unlock();
        }
    }


    public boolean isEmpty() {
        lock.lock();
        try {
            return queue.isEmpty();
        } finally {
            lock.unlock();
        }
    }

    public boolean isFull() {
        lock.lock();
        try {
            return queue.size() == capacity;
        } finally {
            lock.unlock();
        }
    }
}

写在最后

这个CustomBlockingQueue类使用了Java并发包中的ReentrantLock作为锁机制,并通过其条件变量notEmpty和notFull分别管理队列空和队列满的情况。当队列满时,调用put方法会阻塞,直到有空间;当队列空时,调用take方法也会阻塞,直到有元素可消费。同时,当添加或删除元素改变队列状态时,会适当调整对应的条件变量以唤醒等待的线程。

相关推荐
Wang's Blog20 分钟前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
谢亮_vipxieliang29 分钟前
Go map与结构体的正确使用
开发语言·golang·哈希算法
H.莓飛35 分钟前
【C++】命名空间、缺省参数、函数重载与引用
linux·开发语言·c++·visual studio
xxwl5851 小时前
数据结构知识点和代码实现总结(C语言实现)
c语言·开发语言·数据结构
MandalaO_O1 小时前
IDEA 开发(快捷键 + 调试 + 序列化)
java·ide·intellij-idea
xiaoqiMikko2 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
狼爷3 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路3 小时前
zap扩展生态与总结
java·前端·数据库
第七页独白3 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
QCoding4 小时前
Spring AI Alibaba Graph实战:从ReAct Agent到Workflow,企业AI复杂流程该如何编排?
java·人工智能