Java 并发编程·BlockingQueue

作者 : jamin 本文共2235个字,预计阅读时间需要6分钟 发布时间: 2020-10-18 共995人阅读

BlockingQueue

BlockingQueue,即阻塞队列被广泛使用在“生产者-消费者”问题中,其原因是 BlockingQueue 提供了可阻塞的插入和移除的方法。当队列容器已满,生产者线程会被阻塞,直到队列未满;当队列容器为空时,消费者线程会被阻塞,直至队列非空时为止。

BlockingQueue API

BlockingQueue 有 4 种不同的方法来插入、删除和检查队列中的元素。每一组方法的行为都是不同的,以防被请求的操作不能立即执行。以下是 4 种方法的具体分类:

操作 Throws Exception 特殊值 超时 阻塞
Insert add(e) offer(e) offer(e, timeout, timeunit) put(e)
Remove remove(e) poll() poll(timeout, timeunit) take()
Examine element() peek()

这四种不同的行为方式意思:

  • Throws Exception:如果尝试的操作不可能立即发生,则抛出一个异常;
  • 特殊值:如果尝试的操作不能立即执行,则会返回一个特殊值(是否成功 true/false 或者移除/取出的元素);
  • 超时:如果尝试的操作不可能立即执行,则该方法调用将阻塞,但不会超过给定的超时,最终返回与特殊值一样;
  • 阻塞:如果尝试的操作不可能立即执行,那么该方法将阻塞。

无法将 null 插入到 BlockingQueue 中。如果尝试插入 null,则 BlockingQueue 将引发 NullPointerException。

插入元素

  • add(E e):往队列插入数据,当队列满时,插入元素时会抛出 IllegalStateException 异常;
  • offer(E e):当往队列插入数据时,插入成功返回 true,否则则返回 false,当队列满时不会抛出异常;
  • offer(E e, long timeout, TimeUnit unit):若阻塞队列已经满时,同样会阻塞插入数据的线程,直至阻塞队列已经有空余的地方,与 put 方法不同的是,该方法会有一个超时时间,若超过当前给定的超时时间,插入数据的线程会退出;
  • put(E e):当阻塞队列容量已经满时,往阻塞队列插入数据的线程会被阻塞,直至阻塞队列已经有空余的容量可供使用。

删除元素

  • remove(E e):从队列中删除数据,成功则返回 true,否则为 false;
  • poll():删除数据,当队列为空时,返回 null;
  • poll(long timeout, TimeUnit unit):当阻塞队列为空时,获取数据的线程会被阻塞,如果被阻塞的线程超过了给定的时长,该线程会退出;
    take():当阻塞队列为空时,获取队头数据的线程会被阻塞。

查看元素

  • element():获取队头元素,如果队列为空时则抛出 NoSuchElementException 异常;
  • peek():获取队头元素,当队列为空时,返回 null;

常用的 BlockingQueue

ArrayBlockingQueue

ArrayBlockingQueue 是由数组实现的有界阻塞队列。队列元素 FIFO(先进先出),因此,队头元素是存在时间最长的元素,而队尾数据则是最新的元素。

ArrayBlockingQueue 一旦创建,容量不能改变。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。

ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序访问,即最先等待的线程能够最先访问到队列。ArrayBlockingQueue 不能保证公平性则是指访问队列的顺序不是遵守严格的时间顺序,所以有可能存在长时间阻塞的线程依然无法访问到队列。如果保证公平性,通常会降低吞吐量。如果需要获得公平性的 ArrayBlockingQueue,可采用如下代码:

private static ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(10, true);

LinkedBlockingQueue

LinkedBlockingQueue 是用链表实现的有界阻塞队列,同样满足 FIFO 的特性,与 ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止 LinkedBlockingQueue 容量迅速增,损耗大量内存。通常在创建 LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于 Integer.MAX_VALUE。

PriorityBlockingQueue

PriorityBlockingQueue 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。

SynchronousQueue

SynchronousQueue 队列容量为 0,每个插入操作必须等待另一个线程进行相应的删除操作,因此,SynchronousQueue 实际上没有存储任何数据元素,因为只有线程在删除数据时,其他线程才能插入数据,同样的,如果当前有线程在插入数据时,线程才能删除数据。SynchronousQueue 也可以通过构造器参数来为其指定公平性,线程池中的 CachedThreadPool 就是使用 SynchronousQueue。

本站所提供的部分资源来自于网络,版权争议与本站无关,版权归原创者所有!仅限用于学习和研究目的,不得将上述内容资源用于商业或者非法用途,否则,一切后果请用户自负。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源。如果上述内容资对您的版权或者利益造成损害,请提供相应的资质证明,我们将于3个工作日内予以删除。本站不保证所提供下载的资源的准确性、安全性和完整性,源码仅供下载学习之用!如用于商业或者非法用途,与本站无关,一切后果请用户自负!本站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。如有侵权、不妥之处,请联系站长以便删除!
金点网络-全网资源,一网打尽 » Java 并发编程·BlockingQueue

常见问题FAQ

免费下载或者VIP会员专享资源能否直接商用?
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。
是否提供免费更新服务?
持续更新,永久免费
是否经过安全检测?
安全无毒,放心食用

提供最优质的资源集合

立即加入 友好社区
×