面试系列 - 阻塞队列

阻塞队列

java中的阻塞队列在线程池中作为一个构造器的参数存在 BlockingQueue workQueue
阻塞队列的作用一般是用来存储已经submit但还没有执行完毕的线程。在多线程中,阻塞的意思是,在某些情况下会挂起线程,一旦条件成熟,被阻塞的线程就会被自动唤醒。阻塞队列就是用来存储线程池中的这些被挂起的线程的。

特点

先进先出

    /*进队列*/
    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
    
	private void enqueue(E x) {
        // assert lock.getHoldCount() == 1;
        // assert items[putIndex] == null;
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();
    }
	/*出队列*/
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    
	private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();
        return x;
    }
类型

有界队列
无界队列
直接提交队列
优先任务队列

线程池使用队列详情

四种线程池:
并发库中的blockingqueue(阻塞队列),主要提供了两个方法put()和take()
前者将对象放到队列中,如果队列已满,就等待有空闲。后者从head取一个对象,如果没有对象就等到有对象。

FixedThreadPool与SingleThreadPool都是采用的无界linkedblockingqueue实现。linkedblockingqueue中引入了两把锁takelock和putlock,显然分别用于take操作和put操作。入队出队用不同锁,可以同时进行入队出队操作。由于其实链表,查找较慢。

CacheThreadPool使用的时synchronousqueue队列,该队列是一种直接提交队列。

### 关于阻塞队列面试题解析 #### 什么是阻塞队列阻塞队列是一种特殊的队列,在多线程环境下用于处理生产者-消费者模式中的数据传递。当队列为空时,尝试获取元素的操作会被阻塞直到有新的元素加入;同样地,如果队列已满,则试图添加新元素也会被阻塞直至有足够的空间[^2]。 #### Java 中常用的阻塞队列有哪些? Java 提供了几种不同类型的阻塞队列,每一种都有其特定的应用场景: - **ArrayBlockingQueue**: 基于数组结构实现的一个固定大小的阻塞队列- **LinkedBlockingQueue**: 使用链表作为底层存储机制的阻塞队列,默认情况下容量无界。 - **SynchronousQueue**: 特殊形式的队列,其中每一个插入操作都必须等待另一个移除操作匹配它才能继续。 - **PriorityBlockingQueue**: 支持优先级排序功能的无界阻塞队列- **DelayQueue**: 只能从中取出延迟到期后的元素的无界阻塞队列[^1]。 #### 如何防止阻塞队列导致死锁? 为了避免因不当使用阻塞队列而引发死锁情况的发生,应该遵循良好的编程实践,比如始终先检查条件再执行相应动作,并且合理设置超时参数以避免无限期挂起。另外还可以利用`tryPut()` 和 `tryTake()` 方法代替可能会造成永久性阻塞的方法调用[^3]。 ```java // 示例代码展示如何安全地向 LinkedBlockingQueue 添加元素 public void safeAddElement(LinkedBlockingQueue<String> queue, String element){ try { if (!queue.offer(element)) { // 尝试非阻塞地放入元素 System.out.println("Failed to add element due to full queue."); } } catch (Exception e) { System.err.println(e.getMessage()); } } ``` #### 阻塞队列的工作原理是什么样的? 阻塞队列内部维护了一个先进先出(FIFO)的数据序列化容器以及两个同步监视器对象——putLock和takeLock分别用来控制写入端口和读取端口的竞争状况。每当发生入队或者出队行为的时候都会触发相应的通知事件告知其他正在等待该资源可用性的线程去竞争锁进而完成后续操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值