阻塞队列的相关问题

写在前面:前段时间面试的时候,碰到一个面试官针对阻塞队列问了以下几个问题,回答的很不好,感觉是自己的薄弱点,现在整理一下这些知识,如有错误还请各位大佬指正!(写出面试时问的这几个问题)
1. 阻塞队列和非阻塞队列的区别?
2. Java中的线程池参数为什么使用阻塞队列?
3. 手写一个阻塞队列的实现

1、阻塞队列和非阻塞队列

1.1、简介

阻塞队列是一种特殊的队列,支持在队列为空或满时的阻塞操作。相比之下,非阻塞队列则不会阻塞线程,而是通过返回 null 或抛出异常来表示队列为空或满。

1.2、阻塞队列的特点

阻塞队列是一个线程安全的队列,它支持以下特性:

支持阻塞插入操作:当队列已满时,插入操作将被阻塞,直到队列有空闲空间。
支持阻塞删除操作:当队列为空时,删除操作将被阻塞,直到队列中有元素可供删除。
Java 提供了多种实现阻塞队列的类,包括:

  1. ArrayBlockingQueue:基于数组的有界阻塞队列。
  2. LinkedBlockingQueue:基于链表的可选有界阻塞队列。
  3. PriorityBlockingQueue:具有优先级的无界阻塞队列。
  4. SynchronousQueue:不存储元素的阻塞队列。
    接下来,我们将以 ArrayBlockingQueue 为例,介绍如何使用阻塞队列。

1.2.1、创建阻塞队列

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(10);

上述代码创建了一个容量为 10 的 ArrayBlockingQueue 对象。我们可以将其看作是一个装有整数的队列,初始时队列为空。

1.2.2、插入元素

blockingQueue.put(1);

上述代码使用 put 方法向队列中插入元素 1。如果队列已满,则当前线程将被阻塞,直到队列有空闲空间。

1.2.3、删除元素

int element = blockingQueue.take();

上述代码使用 take 方法从队列中删除一个元素,并返回被删除的元素。如果队列为空,则当前线程将被阻塞,直到队列中有元素可供删除。

1.2.4 常见方法

在这里插入图片描述

1.3 非阻塞队列的特点

非阻塞队列是一个线程安全的队列,它不会阻塞线程,而是通过返回 null 或抛出异常来表示队列为空或满。

Java 提供了多种实现非阻塞队列的类,包括:

  1. ConcurrentLinkedQueue:基于链表的无界非阻塞队列。
  2. LinkedTransferQueue:基于链表的无界非阻塞队列。
  3. LinkedBlockingDeque:基于链表的可选有界非阻塞队列。
    下面以 ConcurrentLinkedQueue 为例,介绍如何使用非阻塞队列。

1.3.1 创建非阻塞队列

import java.util.concurrent.ConcurrentLinkedQueue;
ConcurrentLinkedQueue<Integer> nonBlockingQueue = new ConcurrentLinkedQueue<>();

上述代码创建了一个 ConcurrentLinkedQueue 对象。我们可以将其看作是一个装有整数的队列,初始时队列为空。

1.3.2 插入元素

nonBlockingQueue.offer(1);

上述代码使用 offer 方法向队列中插入元素 1。如果队列已满,offer 方法将返回 false。

1.3.3 删除元素

Integer element = nonBlockingQueue.poll();

上述代码使用 poll 方法从队列中删除一个元素,并返回被删除的元素。如果队列为空,poll 方法将返回 null。

1.4 总结

下表展示了阻塞队列和非阻塞队列的主要区别:
在这里插入图片描述

2、Java线程池的参数为什么使用阻塞队列?

网上找了很多解释,我觉得下面这些解释比较让我信服(线程池相当于消费者,队列相当于是生产者,对应于生产者-消费者模型)

  1. 作用一:当一般队列中的任务满了后,阻塞队列可以保留之后的任务,充当一个缓冲区的作用;
  2. 作用二:当队列没有任务时阻塞获取任务的线程、使其进入wait状态,释放CPU资源。阻塞队列自带阻塞和唤醒功能,不需要额外的处理,无任务时线程池利用阻塞队列的take方法挂起,从而保证核心线程的存货,不至于一直占用CPU资源。

3、手写实现阻塞队列

public class BlockingQueue1 {
    private int size = 0;
    private int[] elem;
    private int head = 0, tail = 0;

    public BlockingQueue1(int cap) {
        elem = new int[cap];
    }

    public synchronized void put(int val) {
        while (size == elem.length) {
            // 队列满
            try {
                wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        size++;
        // 队尾进
        elem[tail++] = val;
        if (tail >= elem.length) {
            tail = 0;
        }
        this.notify();
    }

    public synchronized int get() {
        while (size == 0) {
            // 队列为空
            try {
                wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        size--;
        // 队头出
        int val = elem[head++];
        if (head >= elem.length) {
            head = 0;
        }
        this.notify();
        return val;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值