连LinkedBlockingQueue源码都没看过,我怎么敢给你offer?(上)

简介: 连LinkedBlockingQueue源码都没看过,我怎么敢给你offer?(上)

0 前言

LinkedBlockingQueue - 单链表实现的阻塞队列。该队列按 FIFO(先进先出)排序元素,新元素从队列尾部插入,从队首获取元素.是深入并发编程的基础数据结构.

1 继承体系

image.pngQueue 作为最基础的接口,定义了队列的三类基本操作:

image.png

BlockingQueue 基于 Queue 加了阻塞功能:

  • 一直阻塞
  • 阻塞一定时间,返回特殊值

remove 方法,BlockingQueue 类注释中定义的是抛异常,但 LinkedBlockingQueue 中 remove 方法实际是返回 false。

2 属性

2.1 链式存储

  • 节点的数据结构
  • image.png
  • next 为当前元素的下一个,为 null 表示当前节点是最后一个
  • 链表容量
  • image.png
  • 默认大小为 Integer.MAX_VALUE !显然太大了!禁用!
  • image.png
  • 链表已有元素大小

使用了 AtomicInteger,线程安全

image.png

链表头、尾

image.png

2.2 锁

  • take 时的锁
  • image.png
  • take 的条件队列,condition 可理解为基于 ASQ 建立的条件队列
  • image.png
  • put 时的锁
  • image.png
  • put 的条件队列
  • image.png
  • take 锁和 put 锁,是为保证队列操作时的线程安全,设计两种锁,是为了 take 和 put 两种操作可同时进行,互不影响。

2.3 迭代器

  • 实现了自己的迭代器
private class Itr implements Iterator<E> {
    /*
     * Basic weakly-consistent iterator.  At all times hold the next
     * item to hand out so that if hasNext() reports true, we will
     * still have it to return even if lost race with a take etc.
     */
    private Node<E> current;
    private Node<E> lastRet;
    private E currentElement;
    Itr() {
        fullyLock();
        try {
            current = head.next;
            if (current != null)
                currentElement = current.item;
        } finally {
            fullyUnlock();
        }
    }
    public boolean hasNext() {
        return current != null;
    }
    /**
     * Returns the next live successor of p, or null if no such.
     *
     * Unlike other traversal methods, iterators need to handle both:
     * - dequeued nodes (p.next == p)
     * - (possibly multiple) interior removed nodes (p.item == null)
     */
    private Node<E> nextNode(Node<E> p) {
        for (;;) {
            Node<E> s = p.next;
            if (s == p)
                return head.next;
            if (s == null || s.item != null)
                return s;
            p = s;
        }
    }
    public E next() {
        fullyLock();
        try {
            if (current == null)
                throw new NoSuchElementException();
            E x = currentElement;
            lastRet = current;
            current = nextNode(current);
            currentElement = (current == null) ? null : current.item;
            return x;
        } finally {
            fullyUnlock();
        }
    }
    public void remove() {
        if (lastRet == null)
            throw new IllegalStateException();
        fullyLock();
        try {
            Node<E> node = lastRet;
            lastRet = null;
            for (Node<E> trail = head, p = trail.next;
                 p != null;
                 trail = p, p = p.next) {
                if (p == node) {
                    unlink(p, trail);
                    break;
                }
            }
        } finally {
            fullyUnlock();
        }
    }
}
目录
相关文章
|
9月前
|
存储 安全 Java
【面试题精讲】ArrayBlockingQueue 和 LinkedBlockingQueue 区别
【面试题精讲】ArrayBlockingQueue 和 LinkedBlockingQueue 区别
|
9月前
|
存储 安全 Java
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
|
11月前
|
存储 缓存 安全
BlockingQueue阻塞队列原理以及实现
BlockingQueue阻塞队列原理以及实现
89 0
|
11月前
|
算法 NoSQL 前端开发
|
12月前
|
存储 安全 Java
LinkedBlockingQueue 原理
LinkedBlockingQueue 原理
|
缓存 安全 Java
JUC系列学习(四):线程池阻塞队列BlockingQueue及其相关实现ArrayBlockingQueue、LinkedBlockingQueue
线程池阻塞队列BlockingQueue及其相关实现ArrayBlockingQueue、LinkedBlockingQueue
|
安全 Java
LinkedBlockingQueue源码学习
采用线程池和阻塞队列实现生产/消费者模型。其中LinkedBlockingQueue是阻塞队列,同时线程安全,其特点: 采用链表数据结构Node的方式进行节点数据的记录, 同时其进行入队和出队的计数器采用原子性的AtomicInteger 其出队和入队采用采用两把锁,putLock和takeLock,同时进行删除的时候,采用fullLock 其与LinkedBlockingQueue相比,其可以无界可以有界,而ArrayBlockingQueue是有界的,同时实现的数据结构不通过,一个采用数组、一个采用链表,同时采用的锁的方式不同,ArrayBlockingQueue采用一把锁,没有对生产和消
41 0
LinkedBlockingQueue源码学习
|
存储 安全 Java
面试侃集合 | LinkedBlockingQueue篇
面试侃集合 | LinkedBlockingQueue篇
165 0
面试侃集合 | LinkedBlockingQueue篇