java并发编程之阻塞队列

数据结构中队列就是先进先出的结构,加上点算法可以实现优先队列,再加上线程安全就可以形成下图
在这里插入图片描述
这里还多了个阻塞队列,阻塞队列可以凭很生产与消费的速率,即take/put的快慢调节,它是线程安全的,这样就将需要程序员维护的线程安全问题转移到队列上了。

一般数据结构类中都需要定义这个容器的大小,LinkedBlockingQueue 中这个上限值是Integer.MAX_VALUE。

阻塞队列提供了增删方法,但是这些方法可以分为三类,一类是当条件不满足时会抛出异常,一类是不满足条件时会返回bool值,不会抛异常,最后一类就时会阻塞了。
对应方法如下:
在这里插入图片描述
前面给出了java 库中队列的几种形式,其中
ArrayBlockingQueue 就是不可扩容了。类似于golang的指定长度chan。
LinkedBlockingQueue 很明显用链表实现的。
SynchronousQueue 没有容量,类似golang中没有长度的chan。
PriorityBlockingQueue 通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。
DelayQueue 内部使用PriorityQueue 排序,可以看大牛的代码设计是多么nice。

这么多阻塞队列可以按需取用,但是其根本的阻塞原理无外乎就是对临界区加解锁

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length)
        notFull.await();
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

而非阻塞的ConcurrentLinkedQueue 则采用CAS 方法保证线程安全,适合并发不是特别高的情况。

public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);

    for (Node<E> t = tail, p = t;;) {
        Node<E> q = p.next;
        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
        }
        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
            // Check for tail updates after two hops.
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

有这么多阻塞队列,那怎么采用呢,Java线程池的选用为
在这里插入图片描述
FixedThreadPool 线程数一定,任务过多时用LinkedBlockingQueue来接。
ScheduledThreadPool 用DelayedWorkQueue 来实现schedule.。

总结起来就是:
按功能选

需要排序、延迟的选PriorityBlockingQueue

按容量选

固定容量的选 ArrayBlockingQueue

按是否扩容选

从C++开发看,不得不说生态丰富,库函数齐全真是爽。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值