Java中的LinkedBlockingDeque和示例

Java中的LinkedBlockingDeque和示例

LinkedBlockingDeque是Java集合中的一个实现,它是一个线程安全的双向队列,支持高效的插入、删除和遍历操作。它是BlockingDeque接口的一个具体实现,其内部实现使用了链表数据结构。

LinkedBlockingDeque可以用于各种并发编程场景,例如作为生产者和消费者之间的缓存队列,或作为线程池中的工作队列等。

下面我们来看一下LinkedBlockingDeque的一些示例。

初始化LinkedBlockingDeque

创建LinkedBlockingDeque时,可以不指定大小,也可以指定一个容量。如果未指定容量,则默认容量为Integer.MAX_VALUE。

// 初始化一个无限容量的LinkedBlockingDeque
LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

// 初始化一个容量为10的LinkedBlockingDeque
LinkedBlockingDeque<Integer> deque2 = new LinkedBlockingDeque<>(10);

入队和出队操作

入队操作用add(E e)offer(E e)方法,出队操作用remove()poll()方法。如果队列为空,remove()poll()方法会返回null或抛出异常,而add()offer()方法会返回false或抛出异常。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

// 入队操作
deque.add(1); // 添加到队列的尾部
deque.offer(2); // 添加到队列的尾部

// 出队操作
int head = deque.poll(); // 获取队列头部元素并删除

如果想在队列头部或尾部插入元素,可以使用addFirst(E e)addLast(E e)offerFirst(E e)offerLast(E e)等方法。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

// 入队操作
deque.addFirst(1); // 添加到队列的头部
deque.addLast(2); // 添加到队列的尾部

// 出队操作
int head = deque.pollFirst(); // 获取队列头部元素并删除

获取队列元素

除了出队操作之外,还有一些方法可以获取队列中的元素,例如peek()peekFirst()peekLast()方法可以获取队列头部或尾部的元素而不删除它们。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

deque.add(1);
deque.add(2);

System.out.println(deque.peek()); // 输出:1
System.out.println(deque.peekFirst()); // 输出:1
System.out.println(deque.peekLast()); // 输出:2

另外,iterator()方法可以用于迭代队列中的元素。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

deque.add(1);
deque.add(2);

Iterator<Integer> iterator = deque.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

阻塞等待

LinkedBlockingDeque支持阻塞等待操作,当队列为空时,会阻塞调用方线程,直到队列中有元素可以出队或入队时再恢复线程。

take()方法可以获取并删除队列头部元素,如果队列为空,则会一直阻塞线程。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();

// 新开一个线程向队列中添加元素
new Thread(() -> {
    try {
        deque.put(1);
        Thread.sleep(1000);
        deque.put(2);
        Thread.sleep(1000);
        deque.put(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

// 从队列中取出元素
System.out.println(deque.take()); // 阻塞等待,直到队列中有元素
System.out.println(deque.take()); // 阻塞等待,直到队列中有元素
System.out.println(deque.take()); // 阻塞等待,直到队列中有元素

put(E e)方法用于将元素插入到队列尾部,如果队列已满,则会一直阻塞调用方线程,直到队列中有空闲位置可以插入元素。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>(2);

// 新开一个线程向队列中添加元素
new Thread(() -> {
    try {
        deque.put(1);
        deque.put(2); // 队列已满,会阻塞等待
        deque.put(3); // 队列已满,会阻塞等待
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

// 从队列中取出元素
System.out.println(deque.take()); // 输出:1
System.out.println(deque.take()); // 输出:2
System.out.println(deque.take()); // 阻塞等待,直到队列中有元素

并发操作示例

下面是一个并发场景的示例,其中生产者向队列中添加元素,消费者从队列中取出元素并进行处理。

LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>(10);

// 生产者线程
Thread producer = new Thread(() -> {
    for (int i = 1; i <= 100; i++) {
        try {
            deque.put(i); // 队列满时会阻塞等待
            System.out.println("Produced: " + i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});

// 消费者线程
Thread consumer = new Thread(() -> {
    while (true) {
        try {
            int num = deque.take(); // 队列空时会阻塞等待
            System.out.println("Consumed: " + num);
            Thread.sleep(1000); // 模拟耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});

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

结论

Java中的LinkedBlockingDeque提供了一个线程安全的双向队列实现,支持高效的入队、出队和遍历操作,同时也支持阻塞等待的操作。它可以用于各种并发编程场景,例如生产者和消费者之间的缓存队列、线程池中的工作队列等。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程