`
lpbj010
  • 浏览: 2584 次
社区版块
存档分类
最新评论

简析LinkedBlockingQueue类

阅读更多
此类实现了BlockingQueue接口,同时继承了父类AbstractQueue,父类里实现了几个基本方法的调用
add(E e),通过子类的offer(e)具体实现
remove(),通过子类的poll()具体实现
element(),通过子类的peek()具体实现,这几个是常用方法
在LinkedBlockingQueue中,先定义了个Node内部类,这个类是队列中存储的具体的节点类,所以的通过泛型定义的类型都会封装成Node类存储在队列里
	static class Node<E> {  //加static 可以在类中直接定义,不用加外部类名的前缀
        E item;				//定义某个泛型类型变量,存储具体的值

        Node<E> next;       //队列里链表存储机制,这个是定义下一个的节点

        Node(E x) { item = x; }
    }
final int capacity;         //定义此队列的长度,默认是Integer的最大长度Integer.MAX_VALUE
final AtomicInteger count = new AtomicInteger(0); //当前队列的已有个数,定义成AtomicInteger可以在底层实现CAS的原子操作



signalNotEmpty()和signalNotFull()方法在多线程情况下,生产者和消费者模式里进行唤醒操作,类似Object中的notify()方法
队列真实添加节点的方法,所有的入队都会调用

	private void enqueue(Node<E> node) {
         last = last.next = node;     //这句代码相当于  last.next = node; last = last.next; 把节点赋值给最后节点的下一个,最后节点往后推一个
    }
与之对应的是所有的出队都会调用的方法,取头结点指向的节点
	private E dequeue() {
        Node<E> h = head;
        Node<E> first = h.next; 	//获取头结点的下一个节点 first
        h.next = h; // help GC		//释放最开始的头结点
        head = first;				//把first当做头结点
        E x = first.item;			
        first.item = null;			//清空头结点的具体值
        return x;					
    }	

进队方法,基本上进队都是类似操作
    public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        int c = -1;
        Node<E> node = new Node(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();
        try {
            while (count.get() == capacity) {	//如果队列已满,入队锁里的notFull条件生效,开始等待
                notFull.await();
            }
            enqueue(node);
            c = count.getAndIncrement();		//没加这个节点之前,队列中节点个数
            if (c + 1 < capacity)				//加完这个节点后如果还有空地,唤醒一个入队锁里的在notFull条件等待的线程
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)								//如果在加入这个节点前,队列为空,则唤醒一个在出队锁里,在notEmpty条件等待的线程
            signalNotEmpty();
    }



出队方法,基本上出队都是类似操作
    public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
            while (count.get() == 0) {			//如果队列为空,出队锁里notEmpty条件生效,开始等待
                notEmpty.await();
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)							//取出这个节点后如果队列还有值,唤醒一个出队锁里的在notEmpty条件等待的线程
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)						//如果在取出这个节点前,队列是满的,则唤醒一个在入队锁里,在notFull条件等待的线程
            signalNotFull();
        return x;
    }


其他出队入队的方法类似这两个方法,就不多说了。
这个类主要是注意这个队列是用链表进行存储,头结点的item是null,next指向了第一个节点。在多线程同步的时候用了ReentrantLock,定义了出队锁和入队锁,每个所都有自己的condition,所以唤醒的时候回相对精确唤醒某种类型的await。用了AtomicInteger对象做计数器,这个类实现了加减的CAS操作,操作返回的是之前的值。
分享到:
评论

相关推荐

    linkedblockingqueue

    1. 链表结构:`LinkedBlockingQueue`内部由两个节点类`Node`组成,一个表示元素,另一个表示等待的线程。这种设计使得插入和移除操作的时间复杂度为O(1)。 2. 阻塞机制:`LinkedBlockingQueue`通过`Lock`和`...

    LinkedBlockingQueue + 单向链表基本结构

    文件中的类可能定义了一个简单的单向链表节点,包括节点的数据成员(如数据item和指向下一个节点的引用next)以及可能的辅助方法,例如插入新节点、删除节点或者遍历链表等。这些方法需要正确处理并发访问,以确保...

    LinkedBlockingQueue 和 ConcurrentLinkedQueue的区别.docx

    《LinkedBlockingQueue与ConcurrentLinkedQueue的比较与应用》 在Java并发编程中,队列是一种重要的数据结构,尤其在多线程环境下的任务调度和数据传递中扮演着关键角色。LinkedBlockingQueue和...

    并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法

    ### 并发队列 ConcurrentLinkedQueue 和阻塞队列 LinkedBlockingQueue 用法详解 #### 一、并发队列 ConcurrentLinkedQueue 概述 `ConcurrentLinkedQueue` 是 Java 并发包 `java.util.concurrent` 提供的一个高性能...

    LinkedBlockingQueuejava.pdf

    `LinkedBlockingQueue`的内部实现基于两个主要的链接节点类:`Node`和`LinkedBlockingQueue.E`. `Node`用于存储元素,`E`是`Node`的一个内部静态类,实现了`Runnable`接口,用于线程的唤醒。每个节点包含一个元素和...

    详细分析Java并发集合LinkedBlockingQueue的用法

    LinkedBlockingQueue使用链表方式实现的阻塞队列,链表的节点是通过内部类Node实现的。Node类中有两个变量,一个是储存数据的变量item,一个是指向链表的下一个节点的引用next。链表的头节点head和尾节点last是在...

    JDK容器学习之Queue:LinkedBlockingQueue

    在Java的并发编程中,JDK提供的容器类库扮演了重要角色,其中`java.util.concurrent`包下的`BlockingQueue`接口及其实现类是多线程环境下数据同步的重要工具。本篇文章将深入探讨`LinkedBlockingQueue`,这是一个...

    并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解

    它们都继承自AbstractQueue类,并实现了BlockingQueue接口,提供了线程安全的队列操作。 ArrayBlockingQueue实现原理: ArrayBlockingQueue内部使用数组存储元素,使用ReentrantLock来保证线程安全,使用Condition...

    元素唯一的LinkedBlockingQueue阻塞队列

    要实现这一特性,我们通常会自定义队列的元素类,并重写`equals()`和`hashCode()`方法,确保元素比较时的唯一性。同时,队列在插入元素时会进行检查,如果发现新元素与队列中已有的元素相同,则插入操作会被阻止。 ...

    生产者/消费者模式 阻塞队列 LinkedBlockingQueue

    在Java中,阻塞队列(BlockingQueue)是一个很好的实现生产者/消费者模式的工具,而LinkedBlockingQueue则是Java并发包(java.util.concurrent)中提供的一个具体实现。 LinkedBlockingQueue是一个基于链表结构的...

    java中LinkedBlockingQueue与ArrayBlockingQueue的异同

    Java中的`LinkedBlockingQueue`和`ArrayBlockingQueue`都是`java.util.concurrent`包下的线程安全队列,它们都实现了`BlockingQueue`接口,提供了一种高效、线程安全的数据同步方式。这两种队列在很多方面都有相似之...

    喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。.doc

    《Java多线程环境下慎用`LinkedBlockingQueue`的`stream`遍历——揭秘JDK BUG》 在Java编程中,线程安全是多线程编程的重要考量因素,而`LinkedBlockingQueue`作为Java并发包中的一个线程安全队列,因其高效的性能...

    blockingQueues:简单,高性能,goroutine安全队列,可用作资源池或作业队列

    LinkedBlockingQueue :由容器/列表支持的有界阻塞队列 ConcurrentRingBuffer :由片支持的有界无锁队列 安装 go get - u github . com / theodesp / blockingQueues 用法 非阻塞API queue , _ := NewArrayBlock

    Java常见的线程安全的类.docx

    3. BlockingQueue和BlockingDeque:这两个接口提供了线程安全的队列操作,如ArrayBlockingQueue、LinkedBlockingQueue和PriorityBlockingQueue实现了BlockingQueue接口,而LinkedBlockingDeque实现了BlockingDeque...

    JAVA 线程类应用

    此外,Java提供了BlockingQueue接口和其实现(如ArrayBlockingQueue、LinkedBlockingQueue等),它们提供了线程安全的数据结构,方便线程间的异步通信。 线程优先级是另一个重要概念,Java中线程的优先级范围是1...

    java 线程池管理类:Executors_.docx

    ### Java线程池管理类:Executors_ #### 概述 `java.util.concurrent.Executors` 是Java并发编程中一个非常重要的工具类,主要用于创建不同类型的线程池对象。通过使用`Executors`类,开发者可以方便地管理和控制...

    关于java的集合类

    - `LinkedBlockingQueue`、`PriorityQueue`等队列类,满足不同同步和排序需求。 - `NavigableSet`和`NavigableMap`接口,提供了更丰富的导航和查找功能。 理解并熟练运用这些知识点对于Java开发者来说至关重要,...

    day19_阻塞队列、线程池、File类、递归.pdf

    2. **LinkedBlockingQueue**:基于链表实现的有界队列,队列的大小默认为Integer.MAX_VALUE,同样遵循FIFO原则。相比于ArrayBlockingQueue,它的吞吐量通常更高,但在空间占用上更大。 3. **SynchronousQueue**:一...

Global site tag (gtag.js) - Google Analytics