欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > java 常用并发队列- LinkedBlockingDeque

java 常用并发队列- LinkedBlockingDeque

2024/10/25 3:18:38 来源:https://blog.csdn.net/Flying_Fish_roe/article/details/141883188  浏览:    关键词:java 常用并发队列- LinkedBlockingDeque

1. LinkedBlockingDeque 的基本概念

1.1 什么是双端队列?

双端队列(Deque,Double-Ended Queue)是一种支持在两端插入和删除元素的数据结构。它结合了栈和队列的特性,可以作为栈(LIFO)或队列(FIFO)来使用。LinkedBlockingDeque 是双端队列的一个线程安全的阻塞实现,支持在多线程环境中进行安全的并发操作。

1.2 LinkedBlockingDeque 的实现

LinkedBlockingDeque 基于链表结构实现,每个节点包含一个元素和指向前后节点的引用。它是一个双向链表,头节点指向队列的头部,尾节点指向队列的尾部。LinkedBlockingDeque 支持在头部和尾部进行插入和删除操作,操作之间通过锁和条件变量来协调,确保线程安全。

2. LinkedBlockingDeque 的特性

2.1 阻塞操作

LinkedBlockingDeque 提供了阻塞操作,可以在队列已满或为空时自动阻塞操作线程,直到有空间可用或有元素可供取出。主要的阻塞方法包括:

  • 插入操作putFirst(E e)putLast(E e) - 当队列已满时,插入操作会阻塞,直到有空间可用。
  • 移除操作takeFirst()takeLast() - 当队列为空时,移除操作会阻塞,直到有元素可供取出。
2.2 非阻塞操作

LinkedBlockingDeque 也提供了非阻塞操作,允许在操作无法立即完成时返回特殊值。主要的非阻塞方法包括:

  • 插入操作offerFirst(E e)offerLast(E e) - 返回 true 表示插入成功,false 表示队列已满。
  • 移除操作pollFirst()pollLast() - 返回队列头部或尾部的元素,队列为空时返回 null
2.3 超时操作

LinkedBlockingDeque 支持在指定时间内等待操作完成,如果在指定时间内无法完成操作,则返回特殊值。主要的超时方法包括:

  • 插入操作offerFirst(E e, long timeout, TimeUnit unit)offerLast(E e, long timeout, TimeUnit unit) - 等待指定时间后,如果仍然无法插入,则返回 false
  • 移除操作pollFirst(long timeout, TimeUnit unit)pollLast(long timeout, TimeUnit unit) - 等待指定时间后,如果仍然无法移除元素,则返回 null
2.4 双端操作

LinkedBlockingDeque 支持双端操作,能够在队列的头部和尾部进行插入和删除操作,这使得它非常灵活,可以用作栈、队列或两者的结合。

2.5 容量限制

LinkedBlockingDeque 可以指定容量限制,防止队列占用过多内存。当队列达到容量上限时,进一步的插入操作将阻塞或返回失败,直到有空间可用。如果不指定容量限制,LinkedBlockingDeque 将被视为无界队列(实际上容量为 Integer.MAX_VALUE)。

3. LinkedBlockingDeque 的常见用法

LinkedBlockingDeque 可以用于各种多线程场景,以下是一些常见的用法示例。

3.1 生产者-消费者模式

在生产者-消费者模式中,生产者将任务或数据放入队列,消费者从队列中取出任务或数据进行处理。LinkedBlockingDeque 可以用作任务队列,支持在任务队列满时阻塞生产者,以及在任务队列空时阻塞消费者。

import java.util.concurrent.LinkedBlockingDeque;public class ProducerConsumerExample {private static final LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>(10);public static void main(String[] args) {Thread producer = new Thread(() -> {try {for (int i = 0; i < 20; i++) {deque.putLast("Task " + i);System.out.println("Produced: Task " + i);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread consumer = new Thread(() -> {try {while (true) {String task = deque.takeFirst();System.out.println("Consumed: " + task);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producer.start();consumer.start();}
}

在这个示例中,生产者线程将任务添加到 LinkedBlockingDeque 的尾部,消费者线程从头部取出任务进行处理。当队列已满时,生产者将阻塞,直到有空间可用;当队列为空时,消费者将阻塞,直到有新任务可供处理。

3.2 双端队列的使用

LinkedBlockingDeque 可以作为双端队列使用,支持在两端进行插入和删除操作。例如,在任务调度系统中,可以根据任务的优先级选择从队列的头部或尾部插入和删除任务。

LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>();// 在头部添加高优先级任务
deque.putFirst("High Priority Task");// 在尾部添加普通任务
deque.putLast("Regular Task");// 获取并处理高优先级任务
String highPriorityTask = deque.takeFirst();// 获取并处理普通任务
String regularTask = deque.takeLast();

这种双端操作的灵活性,使得 LinkedBlockingDeque 可以用于多种复杂的场景,例如任务调度、消息传递等。

4. LinkedBlockingDeque 的优缺点

4.1 优点
  • 线程安全LinkedBlockingDeque 通过内部的锁和条件变量机制确保了在多线程环境下的线程安全性,避免了数据竞争和一致性问题。

  • 灵活性:支持在队列的两端进行插入和删除操作,可以根据需求实现栈、队列或混合使用。

  • 阻塞操作:提供了阻塞的插入和删除方法,使其适合用于生产者-消费者模式等需要等待的场景。

  • 容量限制:可以通过指定容量限制队列的大小,防止内存消耗过大。

4.2 缺点
  • 性能开销:由于内部使用锁和条件变量,LinkedBlockingDeque 的性能可能在高并发场景下受到限制,特别是在频繁的插入和删除操作时。

  • 内存消耗:链表结构在插入大量元素时可能会占用较多内存,尤其是在无界模式下。

  • 复杂性:双端队列的操作较为复杂,可能需要开发者对其特性有较深入的理解,才能正确地应用于实际场景中。

5. 实际应用场景

5.1 任务调度系统

在任务调度系统中,LinkedBlockingDeque 可以用来管理待执行的任务列表。根据任务的优先级,可以选择将高优先级任务插入到队列的头部,而将低优先级任务插入到尾部。消费者线程可以根据需要从队列的头部或尾部取出任务执行。

5.2 消息处理系统

在消息处理系统中,LinkedBlockingDeque 可以用作消息队列。生产者线程将消息插入队列,消费者线程从队列中取出消息进行处理。双端队列的特性使得处理高优先级消息和普通消息更加灵活。

5.3 工作流引擎

在工作流引擎中,LinkedBlockingDeque 可以用来管理工作流任务的执行顺序。根据任务的依赖关系,可以灵活地在队列的头部或尾部插入任务,确保工作流的顺序执行。

6. 与其他队列的比较

6.1 LinkedBlockingDeque vs LinkedBlockingQueue

LinkedBlockingDequeLinkedBlockingQueue 的双端版本,支持在队列的两端进行操作。而 LinkedBlockingQueue 只能在队列的一端插入,另一端移除。`LinkedBlocking

Deque` 的灵活性更强,但同时也带来了更高的复杂性。

6.2 LinkedBlockingDeque vs ArrayBlockingQueue

LinkedBlockingDeque 基于链表实现,支持动态扩展和收缩,而 ArrayBlockingQueue 基于数组实现,必须在创建时指定固定容量。链表结构的 LinkedBlockingDeque 更适合处理动态变化的数据,而 ArrayBlockingQueue 更适合容量固定且需要高性能的场景。

7. 结论

LinkedBlockingDeque 是 Java 并发编程中非常有用的工具,特别适用于需要灵活处理双端操作的多线程场景。它的阻塞操作、容量限制以及线程安全性使其在生产者-消费者模式、任务调度和消息处理等领域中得到了广泛应用。然而,由于其性能开销和复杂性,开发者在使用时需要权衡其优缺点,并根据具体的应用场景选择合适的并发队列。
LinkedBlockingDeque 是 Java 中常用的并发队列之一,位于 java.util.concurrent 包中。它是一个线程安全的双端阻塞队列(Deque),支持在两端进行插入和删除操作。LinkedBlockingDeque 通过内部链表实现,可以指定容量上限,也可以不指定容量(默认为 Integer.MAX_VALUE),使其成为无界队列。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com