日常记录——多线程与高并发—并发容器queue的实现类ConcurrentLinkedQueue、继承接口BlockingQueue

1.ConcurrentLinkedQueue:是一个适用于高并发场景下链接节点的无界线程安全队列,基于cas支持高并发,非阻塞队列。
add方法:

	public boolean add(E e) {
        return offer(e);
	}
	public boolean offer(E e) {
		//为空抛出异常
        checkNotNull(e);
        //创建新节点
        final Node<E> newNode = new Node<E>(e);
		//获取尾结点
        for (Node<E> t = tail, p = t;;) {
        	//尾结点的下一节点  正常为null
            Node<E> q = p.next;
            //如果为null  自旋将新节点设置为尾结点  成功返回true
            if (q == null) {
                // p is last node
                if (p.casNext(null, newNode)) {
                    // Successful CAS is the linearization point
                    // for e to become an element of this queue,
                    // and for newNode to become "live".
                    if (p != t) // hop two nodes at a time
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            //并发条件下的处理  更新尾结点的值  赋值给p
            else if (p == q)
                // We have fallen off list.  If tail is unchanged, it
                // will also be off-list, in which case we need to
                // jump to head, from which all live nodes are always
                // reachable.  Else the new tail is a better bet.
                p = (t != (t = tail)) ? t : head;
            else //否则  继续更新尾结点的值  赋值给p
                // Check for tail updates after two hops.
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

2.BlockingQueue:可以提供阻塞功能的队列。
提供方法:

入队 出队 查看
add(e) 可能抛异常 remove() 可能抛异常 element()
put(e) 可能阻塞 take() 可能阻塞 peek()
offer(e)返回boolean poll()
offer(e, timeout, unit)返回boolean poll(timeout, unit)

接口实现类包含:
ArrayBlockingQueue:有界限队列,初始化需要设定长度,基于ReentrantLock支持线程并发。
offer方法:检查是否为null,为空抛出异常,队列满返回false,否则入队列 返回true

public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

LinkedBlockingQueue:无界队列,默认最大值为Integer.MAX_VALUE,也可以设定长度限制,基于AtomicInteger、ReentrantLock实现线程并发。
offer方法:检查是否为null,为空抛出异常,队列满返回false,否则入队列 返回true

public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final AtomicInteger count = this.count;
        if (count.get() == capacity)
            return false;
        int c = -1;
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        putLock.lock();
        try {
            if (count.get() < capacity) {
                enqueue(node);
                c = count.getAndIncrement();
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }

SynchronousQueue:无内容队列,容量为0,take和put必须同时出现,否则阻塞,用作线程间任务调度。基于cas实现线程安全。
示例代码:put和take缺少一个 都将一直自旋等待

 BlockingQueue<String> synQueue = new SynchronousQueue<>();
        new Thread(() ->{
            try {
                synQueue.put("1");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() ->{
            try {
                System.out.println(synQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

PriorityBlockingQueue:基于优先级的无界阻塞队列,队列的对象必须实现Comparable接口,String,int等为自然顺序。基于ReentrantLock实现线程安全。
示例代码:

 		BlockingQueue proQueue = new PriorityBlockingQueue();
        proQueue.offer(1);
        proQueue.offer(3);
        proQueue.offer(2);
        //person类未实现Comparable 抛出异常
//        proQueue.offer(new Person(1));
        System.out.println(proQueue.poll());
        System.out.println(proQueue.poll());
        System.out.println(proQueue.poll());
class Person{
    private int age ;
    Person(int age){
        this.age = age;
    }

}

DelayQueue:时间排序无界队列,放入对象必须实现Delayed接口,基于ReentrantLock实现线程安全。
示例代码:

 		BlockingQueue<Timeer> proQueue = new DelayQueue();
        long now = System.currentTimeMillis();
        proQueue.put(new Timeer(now+1000,"t1"));
        proQueue.put(new Timeer(now+5000,"t2"));
        proQueue.put(new Timeer(now+500,"t3"));
        System.out.println(proQueue.take());
        System.out.println(proQueue.take());
        System.out.println(proQueue.take());
class Timeer implements Delayed{
    private String name;
    private long time ;
    Timeer(long time,String name){
        this.time = time;
        this.name = name;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(time - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        if(this.getDelay(TimeUnit.MILLISECONDS)<o.getDelay(TimeUnit.MILLISECONDS)){
            return -1;
        } else if(this.getDelay(TimeUnit.MILLISECONDS)>o.getDelay(TimeUnit.MILLISECONDS)){
            return 1;
        }else{
            return 0;
        }
    }

    @Override
    public String toString() {
        return "Timeer{" +
                "name='" + name + '\'' +
                '}';
    }
}

LinkedTransferQueue:链表结构组成的无界阻塞队列,基于LockSupport、cas实现线程并发安全。内含transfer入队方法,如果添加元素未出队则一直阻塞当前线程。
示例代码:

 LinkedTransferQueue<String>  linkedTransferQueue = new LinkedTransferQueue<>();
        new Thread(() ->{
            try {
                System.out.println("我入队了");
                linkedTransferQueue.transfer("a");
                System.out.println("我出队了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() ->{
            try {
                //睡两秒后获取
                TimeUnit.MILLISECONDS.sleep(2000);
                linkedTransferQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

LinkedBlockingDeque:一个线程安全的双端队列实现,内部实现维护了前端和后端节点,基于ReentrantLock实现线程安全。
示例代码:

LinkedBlockingDeque linkedBlockingDeque =new LinkedBlockingDeque();
        //添加头元素
        linkedBlockingDeque.addFirst(1);
        linkedBlockingDeque.addFirst(2);
        linkedBlockingDeque.addFirst(3);
        //添加尾元素
        linkedBlockingDeque.addLast(4);
        linkedBlockingDeque.addLast(5);
        linkedBlockingDeque.addLast(6);
        //取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());
        //查看尾元素
        System.out.println(linkedBlockingDeque.peekLast());
        //取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());
        //取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());//取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());//取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());//取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());//取出尾元素
        System.out.println(linkedBlockingDeque.pollLast());

猜你喜欢

转载自blog.csdn.net/weixin_43001336/article/details/107293676