面试题:你使用过 Java 中的哪些阻塞队列?

Java 中的 阻塞队列(BlockingQueue) 是 java.util.concurrent 包中提供的一种线程安全的队列实现。它支持在队列为空时阻塞获取操作,在队列满时阻塞插入操作。以下是 Java 中常见的阻塞队列及其特点:


1. ArrayBlockingQueue

  • 特点
    • 基于数组实现的有界阻塞队列。
    • 队列容量固定,创建时需要指定容量。
    • 支持公平锁和非公平锁(默认是非公平锁)。
  • 适用场景
    • 适合需要固定大小的队列场景。

2. LinkedBlockingQueue

  • 特点
    • 基于链表实现的可选有界或无界阻塞队列。
    • 如果不指定容量,默认是无界队列(Integer.MAX_VALUE)。
    • 吞吐量通常高于 ArrayBlockingQueue
  • 适用场景
    • 适合任务队列、线程池任务缓冲等场景。

3. PriorityBlockingQueue

  • 特点
    • 基于堆实现的无界阻塞队列。
    • 元素必须实现 Comparable 接口,或者通过构造函数传入 Comparator
    • 队列中的元素按优先级排序,优先级高的元素先出队。
  • 适用场景
    • 适合需要按优先级处理任务的场景。

4. DelayQueue

  • 特点
    • 基于优先级队列实现的无界阻塞队列。
    • 元素必须实现 Delayed 接口,指定延迟时间。
    • 只有延迟时间到期的元素才能被取出。
  • 适用场景
    • 适合定时任务调度、缓存过期等场景。
  • 示例代码
    class DelayedElement implements Delayed {
        private String data;
        private long delayTime;
    
        public DelayedElement(String data, long delayTime) {
            this.data = data;
            this.delayTime = System.currentTimeMillis() + delayTime;
        }
    
        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }
    
        @Override
        public int compareTo(Delayed o) {
            return Long.compare(this.delayTime, ((DelayedElement) o).delayTime);
        }
    
        @Override
        public String toString() {
            return data;
        }
    }
    
    BlockingQueue<DelayedElement> queue = new DelayQueue<>();
    queue.put(new DelayedElement("Task 1", 3000)); // 3秒后到期
    queue.put(new DelayedElement("Task 2", 1000)); // 1秒后到期
    
    System.out.println(queue.take()); // 1秒后输出 "Task 2"
    System.out.println(queue.take()); // 3秒后输出 "Task 1"

5. SynchronousQueue

  • 特点
    • 不存储元素的阻塞队列。
    • 每个插入操作必须等待另一个线程的移除操作,反之亦然。
    • 适合直接传递任务的场景。
  • 适用场景
    • 适合线程之间直接传递数据的场景,如线程池的任务传递。
  • 示例代码
    BlockingQueue<String> queue = new SynchronousQueue<>();
    
    new Thread(() -> {
        try {
            System.out.println("Thread 1 putting item");
            queue.put("Item");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    
    new Thread(() -> {
        try {
            Thread.sleep(1000);
            System.out.println("Thread 2 taking item: " + queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();

6. LinkedTransferQueue

  • 特点
    • 基于链表实现的无界阻塞队列。
    • 支持 transfer() 方法,生产者可以等待消费者取走元素后再返回。
    • 性能优于 SynchronousQueue 和 LinkedBlockingQueue
  • 适用场景
    • 适合需要高效传递任务的场景。
  • 示例代码
    TransferQueue<String> queue = new LinkedTransferQueue<>();
    
    new Thread(() -> {
        try {
            System.out.println("Thread 1 transferring item");
            queue.transfer("Item"); // 等待消费者取走
            System.out.println("Thread 1 transfer complete");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    
    new Thread(() -> {
        try {
            Thread.sleep(1000);
            System.out.println("Thread 2 taking item: " + queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();

7. 总结

  • ArrayBlockingQueue:固定大小的有界队列,适合需要控制队列大小的场景。
  • LinkedBlockingQueue:可选有界或无界队列,适合任务队列和线程池缓冲。
  • PriorityBlockingQueue:无界优先级队列,适合按优先级处理任务的场景。
  • DelayQueue:无界延迟队列,适合定时任务调度。
  • SynchronousQueue:不存储元素的队列,适合直接传递任务。
  • LinkedTransferQueue:高效的无界队列,支持生产者等待消费者。
THE END
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容