线程并发学习----队列(Queue)

线程并发学习

线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify、join)
线程并发学习—-线程阻塞(synchronized)
线程并发学习—-线程阻塞(lock)
线程并发学习—-Thread、Runnable、Callable
线程并发学习—-队列(Queue)
spring学习—-线程池
java中一些锁概念整理(转载)

Queue类图

线程并发学习----队列(Queue)_第1张图片

Queue简介

public interface Queue<E> extends Collection<E> {
    boolean add(E e);
    boolean offer(E e);
    E remove();
    E poll();
    E element();
    E peek();
}

public interface BlockingQueue<E> extends Queue<E> {
    //入队元素,队列满了会抛出异常   底层调用offer实现  
    boolean add(E e);
    //入队元素  队列满了直接返回false
    boolean offer(E e);
    //入队元素  队列满了 则等待
    void put(E e) throws InterruptedException;
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;
    //出队    
    E take() throws InterruptedException;
    //出队
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;
    int remainingCapacity();
    boolean remove(Object o);
    public boolean contains(Object o);
}

public abstract class AbstractQueue<E>
    extends AbstractCollection<E>
    implements Queue<E> {
    protected AbstractQueue() {
    }
    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
    public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }
    ....

从上面的源码码可以看出

添加方法:

add(E e); //入队元素,队列满了会抛出异常 底层调用offer实现
offer(E e); //入队元素 队列满了直接返回false
put(E e); //入队元素 队列满了 则等待

获取方法

element 底层调用peek实现
peek 队列为空时,返回null

移除方法

remove 移除元素 没有元素抛出异常 底层调用poll
poll 移除元素 没有返回null
take 移除元素 没有则等待

常用队列

ArrayBlockingQueue

简介

  • ArrayBlockingQueue是一个阻塞队列,底层使用数组结构实现,按照先进先出(FIFO)的原则对元素进行排序
  • ArrayBlockingQueue是一个线程安全的集合,使用ReentrantLock的非公平锁,保证线程安全,在并发情况下可以保证数据的一致性
  • ArrayBlockingQueue大小是有限的,大小在初始化的时候就确定了,不会自动扩容,是一个“有界缓存区”

部分源码

    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
     public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }
    //入队底层实现,定义为私有方法
    private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();
    }
    //出队底层实现,定义为私有方法
    private E dequeue() {
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();
        return x;
    }

LinkedBlockingQueue

简介

  • LinkedBlockingQueue是一个阻塞队列,底层使用链表结构实现,实现先进先出(FIFO)的原则
  • LinkedBlockingQueue是一个线程安全的集合,使用ReentrantLock的非公平锁,保证线程安全,在并发情况下可以保证数据的一致性(有两把锁,一把读锁,一把写锁)
  • LinkedBlockingQueue一般认为是无限的,默认大小为int的最大值2147483647

    入队: 首先,将最后的结点指向新插入的结点,其次将last结点置为新插入的结点,流程结束!
    出队: 头部元素永远为null

部分源码

//LinkedBlockingQueue 可以实现了两把锁,可以同时读写,在同时出队入队时,都会涉及到对元素数量的并发修改,会有线程安全的问题,故计数使用原子类,底层使用CAS解决数据安全问题
private final AtomicInteger count = new AtomicInteger();

static class Node {
        E item;
        Node next;
        Node(E x) { item = x; }
    }

public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
    public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node(null);
    }
    //入队
    private void enqueue(Node node) {
        last = last.next = node;
    }

    //出队
    private E dequeue() {
        // assert takeLock.isHeldByCurrentThread();
        // assert head.item == null;
        Node h = head;
        Node first = h.next;
        h.next = h; // help GC
        head = first;
        E x = first.item;
        first.item = null;
        return x;
    }

ArrayBlockingQueue与LinkedBlockingQueue比较

  • ArrayBlockingQueue使用数组实现,有界,必须指定数组大小;LinkedBlockingQueue使用链表实现,默认为无界(最大2147483647)
  • ArrayBlockingQueue和LinkedBlockingQueue都使用ReetrantLock
  • ArrayBlockingQueue只有一把锁,只能入队或出队一个在执行;LinkedBlockingQueue有两把锁,可以做到同一时刻既消费、又生产。多个CPU的时候LinkedBlockingQueue性能要更好一点

参考资料
http://mp.weixin.qq.com/s/Ft2y0yBSzF-mUSK8Iwhemw
http://mp.weixin.qq.com/s/0yfjpbZBcTN7ntZJnyJ-Sg
http://mp.weixin.qq.com/s/3yXZXwRKMOBMo8G6WpOmyw

你可能感兴趣的:(线程并发)