Link Blocking Queue

default

LinkedBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个线程安全的阻塞队列实现,基于链表结构。它遵循 FIFO(先进先出) 原则,支持高并发的生产者和消费者操作。以下是它的核心使用方法和注意事项:


1. 创建实例

LinkedBlockingQueue 可以是有界或无界队列:

1
2
3
4
5
// 无界队列(默认容量为 Integer.MAX_VALUE)
LinkedBlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();

// 有界队列(容量为 100)
LinkedBlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(100);

2. 核心方法

生产者方法

  • put(E e)

    将元素插入队列尾部。如果队列已满,阻塞线程直到队列有空间。

    1
    
    queue.put(42); // 阻塞直到插入成功
    
  • offer(E e)

    尝试插入元素。若队列已满,立即返回 false,不阻塞。

    1
    
    boolean success = queue.offer(42); // 非阻塞
    
  • offer(E e, long timeout, TimeUnit unit)

    在指定时间内尝试插入元素,超时返回 false

    1
    
    boolean success = queue.offer(42, 1, TimeUnit.SECONDS); // 最多等待1秒
    
  • add(E e)

    插入元素,若队列已满,抛出 IllegalStateException

    1
    
    queue.add(42); // 可能抛出异常
    

消费者方法

  • take()

    移除并返回队列头部元素。若队列为空,阻塞线程直到有元素。

    1
    
    Integer value = queue.take(); // 阻塞直到获取元素
    
  • poll()

    尝试移除并返回头部元素。若队列为空,立即返回 null

    1
    
    Integer value = queue.poll(); // 非阻塞
    
  • poll(long timeout, TimeUnit unit)

    在指定时间内尝试获取元素,超时返回 null

    1
    
    Integer value = queue.poll(1, TimeUnit.SECONDS); // 最多等待1秒
    
  • peek()

    查看队列头部元素但不移除,若队列为空返回 null

    1
    
    Integer value = queue.peek();
    

3. 示例代码:生产者-消费者模型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.concurrent.LinkedBlockingQueue;

public class ProducerConsumerExample {
    private static final LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

    public static void main(String[] args) {
        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 20; i++) {
                    queue.put(i);
                    System.out.println("Produced: " + i);
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    Integer value = queue.take();
                    System.out.println("Consumed: " + value);
                    Thread.sleep(200);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        producer.start();
        consumer.start();
    }
}

4. 关键特性

  • 线程安全:所有操作都是原子的,适合多线程环境。

  • 阻塞机制put()take() 会在队列满/空时阻塞线程。

  • 可选容量:无界队列可能导致内存问题,建议根据场景设置合理容量。

  • 公平性:默认不保证线程公平访问,但可通过构造函数设置公平策略(依赖 ReentrantLock)。


5. 注意事项

  • 内存风险:无界队列(默认)可能导致内存耗尽,需谨慎使用。

  • 中断处理:阻塞方法可能抛出 InterruptedException,需正确处理中断。

  • 性能优化:多生产者和消费者场景下,LinkedBlockingQueue 通常比 ArrayBlockingQueue 吞吐量更高。


Comments
  • Latest
  • Oldest
  • Hottest
No comment yet.
Powered by Waline v2.15.8
Gear(夕照)的博客。记录开发、生活,以及一些不足为道的思考……