当前位置: 首页 > news >正文

营销型网站建设推广织梦网站修改使用教程

营销型网站建设推广,织梦网站修改使用教程,站长工具大全,手机网站排名第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别#xff1f; 在上一讲中#xff0c;我分析了 Java 并发包中的部分内容#xff0c;今天我来介绍一下线程安全队列。Java 标准库提供了非常多的线程安全队列#xff0c;很容易混淆。 今天我要问你的…第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别 在上一讲中我分析了 Java 并发包中的部分内容今天我来介绍一下线程安全队列。Java 标准库提供了非常多的线程安全队列很容易混淆。 今天我要问你的问题是并发包中的 ConcurrentLinkedQueue 和 LinkedBlockingQueue 有什么区别 典型回答 有时候我们把并发包下面的所有容器都习惯叫作并发容器但是严格来讲类似 ConcurrentLinkedQueue 这种“Concurrent*”容器才是真正代表并发。 关于问题中它们的区别 Concurrent 类型基于 lock-free在常见的多线程访问场景一般可以提供较高吞吐量 而 LinkedBlockingQueue 内部则是基于锁并提供了 BlockingQueue 的等待性方法。 不知道你有没有注意到java.util.concurrent 包提供的容器Queue、List、Set、Map从命名上可以大概区分为 Concurrent*、CopyOnWrite和 Blocking等三类同样是线程安全容器可以简单认为 Concurrent 类型没有类似 CopyOnWrite 之类容器相对较重的修改开销。 但是凡事都是有代价的Concurrent 往往提供了较低的遍历一致性。你可以这样理解所谓的弱一致性例如当利用迭代器遍历时如果容器发生修改迭代器仍然可以继续进行遍历。 与弱一致性对应的就是我介绍过的同步容器常见的行为“fail-fast”也就是检测到容器在遍历过程中发生了修改则抛出 ConcurrentModificationException不再继续遍历。 弱一致性的另外一个体现是size 等操作准确性是有限的未必是 100% 准确。 与此同时读取的性能具有一定的不确定性。 考点分析 今天的问题是又是一个引子考察你是否了解并发包内部不同容器实现的设计目的和实现区别。 队列是非常重要的数据结构我们日常开发中很多线程间数据传递都要依赖于它Executor 框架提供的各种线程池同样无法离开队列。面试官可以从不同角度考察比如 哪些队列是有界的哪些是无界的很多同学反馈了这个问题 针对特定场景需求如何选择合适的队列实现 从源码的角度常见的线程安全队列是如何实现的并进行了哪些改进以提高性能表现 为了能更好地理解这一讲需要你掌握一些基本的队列本身和数据结构方面知识如果这方面知识比较薄弱《数据结构与算法分析》是一本比较全面的参考书专栏还是尽量专注于 Java 领域的特性。 知识扩展 线程安全队列一览 我在专栏第 8 讲中介绍过常见的集合中如 LinkedList 是个 Deque只不过不是线程安全的。下面这张图是 Java 并发类库提供的各种各样的线程安全队列实现注意图中并未将非线程安全部分包含进来。 我们可以从不同的角度进行分类从基本的数据结构的角度分析有两个特别的Deque实现ConcurrentLinkedDeque 和 LinkedBlockingDeque。Deque 的侧重点是支持对队列头尾都进行插入和删除所以提供了特定的方法如: 尾部插入时需要的addLast(e)、offerLast(e)。 尾部删除所需要的removeLast()、pollLast()。 从上面这些角度能够理解 ConcurrentLinkedDeque 和 LinkedBlockingQueue 的主要功能区别也就足够日常开发的需要了。但是如果我们深入一些通常会更加关注下面这些方面。 从行为特征来看绝大部分 Queue 都是实现了 BlockingQueue 接口。在常规队列操作基础上Blocking 意味着其提供了特定的等待性操作获取时take等待元素进队或者插入时put等待队列出现空位。 /*** 获取并移除队列头结点如果必要其会等待直到队列出现元素 …*/ E take() throws InterruptedException;/*** 插入元素如果队列已满则等待直到队列出现空闲空间…*/ void put(E e) throws InterruptedException; 另一个 BlockingQueue 经常被考察的点就是是否有界Bounded、Unbounded这一点也往往会影响我们在应用开发中的选择我这里简单总结一下。 ArrayBlockingQueue 是最典型的的有界队列其内部以 final 的数组保存数据数组的大小就决定了队列的边界所以我们在创建 ArrayBlockingQueue 时都要指定容量如 public ArrayBlockingQueue(int capacity, boolean fair)LinkedBlockingQueue容易被误解为无边界但其实其行为和内部代码都是基于有界的逻辑实现的只不过如果我们没有在创建队列时就指定容量那么其容量限制就自动被设置为 Integer.MAX_VALUE成为了无界队列。 SynchronousQueue这是一个非常奇葩的队列实现每个删除操作都要等待插入操作反之每个插入操作也都要等待删除动作。那么这个队列的容量是多少呢是 1 吗其实不是的其内部容量是 0。 PriorityBlockingQueue 是无边界的优先队列虽然严格意义上来讲其大小总归是要受系统资源影响。 DelayedQueue 和 LinkedTransferQueue 同样是无边界的队列。对于无边界的队列有一个自然的结果就是 put 操作永远也不会发生其他 BlockingQueue 的那种等待情况 如果我们分析不同队列的底层实现BlockingQueue 基本都是基于锁实现一起来看看典型的 LinkedBlockingQueue。 /** Lock held by take, poll, etc */ private final ReentrantLock takeLock new ReentrantLock();/** Wait queue for waiting takes */ private final Condition notEmpty takeLock.newCondition();/** Lock held by put, offer, etc */ private final ReentrantLock putLock new ReentrantLock();/** Wait queue for waiting puts */ private final Condition notFull putLock.newCondition();我在介绍 ReentrantLock 的条件变量用法的时候分析过 ArrayBlockingQueue不知道你有没有注意到其条件变量与 LinkedBlockingQueue 版本的实现是有区别的。notEmpty、notFull 都是同一个再入锁的条件变量而 LinkedBlockingQueue 则改进了锁操作的粒度头、尾操作使用不同的锁所以在通用场景下它的吞吐量相对要更好一些。 下面的 take 方法与 ArrayBlockingQueue 中的实现也是有不同的由于其内部结构是链表需要自己维护元素数量值请参考下面的代码。 public E take() throws InterruptedException {final E x;final int c;final AtomicInteger count this.count;final ReentrantLock takeLock this.takeLock;takeLock.lockInterruptibly();try {while (count.get() 0) {notEmpty.await();}x dequeue();c count.getAndDecrement();if (c 1)notEmpty.signal();} finally {takeLock.unlock();}if (c capacity)signalNotFull();return x; }类似 ConcurrentLinkedQueue 等则是基于 CAS 的无锁技术不需要在每个操作时使用锁所以扩展性表现要更加优异。 相对比较另类的 SynchronousQueue在 Java 6 中其实现发生了非常大的变化利用 CAS 替换掉了原本基于锁的逻辑同步开销比较小。它是 Executors.newCachedThreadPool() 的默认队列。 队列使用场景与典型用例 在实际开发中我提到过 Queue 被广泛使用在生产者 - 消费者场景比如利用 BlockingQueue 来实现由于其提供的等待机制我们可以少操心很多协调工作你可以参考下面样例代码 import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue;public class ConsumerProducer {public static final String EXIT_MSG Good bye!;public static void main(String[] args) { // 使用较小的队列以更好地在输出中展示其影响BlockingQueueString queue new ArrayBlockingQueue(3);Producer producer new Producer(queue);Consumer consumer new Consumer(queue);new Thread(producer).start();new Thread(consumer).start();}static class Producer implements Runnable {private BlockingQueueString queue;public Producer(BlockingQueueString q) {this.queue q;}Overridepublic void run() {for (int i 0; i 20; i) {try{Thread.sleep(5L);String msg Message i;System.out.println(Produced new item: msg);queue.put(msg);} catch (InterruptedException e) {e.printStackTrace();}}try {System.out.println(Time to say good bye!);queue.put(EXIT_MSG);} catch (InterruptedException e) {e.printStackTrace();}}}static class Consumer implements Runnable{private BlockingQueueString queue;public Consumer(BlockingQueueString q){this.queueq;}Overridepublic void run() {try{String msg;while(!EXIT_MSG.equalsIgnoreCase( (msg queue.take()))){System.out.println(Consumed item: msg);Thread.sleep(10L);}System.out.println(Got exit message, bye!);}catch(InterruptedException e) {e.printStackTrace();}}} }上面是一个典型的生产者 - 消费者样例如果使用非 Blocking 的队列那么我们就要自己去实现轮询、条件判断如检查 poll 返回值是否 null等逻辑如果没有特别的场景要求Blocking 实现起来代码更加简单、直观。 前面介绍了各种队列实现在日常的应用开发中如何进行选择呢 以 LinkedBlockingQueue、ArrayBlockingQueue 和 SynchronousQueue 为例我们一起来分析一下根据需求可以从很多方面考量 考虑应用场景中对队列边界的要求。ArrayBlockingQueue 是有明确的容量限制的而 LinkedBlockingQueue 则取决于我们是否在创建时指定SynchronousQueue 则干脆不能缓存任何元素。 从空间利用角度数组结构的 ArrayBlockingQueue 要比 LinkedBlockingQueue 紧凑因为其不需要创建所谓节点但是其初始分配阶段就需要一段连续的空间所以初始内存需求更大。 通用场景中LinkedBlockingQueue 的吞吐量一般优于 ArrayBlockingQueue因为它实现了更加细粒度的锁操作。 ArrayBlockingQueue 实现比较简单性能更好预测属于表现稳定的“选手”。 如果我们需要实现的是两个线程之间接力性handoff的场景按照专栏上一讲的例子你可能会选择 CountDownLatch但是SynchronousQueue也是完美符合这种场景的而且线程间协调和数据传输统一起来代码更加规范。 可能令人意外的是很多时候 SynchronousQueue 的性能表现往往大大超过其他实现尤其是在队列元素较小的场景。 今天我分析了 Java 中让人眼花缭乱的各种线程安全队列试图从几个角度让每个队列的特点更加明确进而希望减少你在日常工作中使用时的困扰。 一课一练 关于今天我们讨论的题目你做到心中有数了吗 今天的内容侧重于 Java 自身的角度面试官也可能从算法的角度来考察所以今天留给你的思考题是指定某种结构比如栈用它实现一个 BlockingQueue实现思路是怎样的呢 请你在留言区写写你对这个问题的思考我会选出经过认真思考的留言送给你一份学习奖励礼券欢迎你与我一起讨论。 你的朋友是不是也在准备面试呢你可以“请朋友读”把今天的题目分享给好友或许你能帮到他。 角度让每个队列的特点更加明确进而希望减少你在日常工作中使用时的困扰。 一课一练 关于今天我们讨论的题目你做到心中有数了吗 今天的内容侧重于 Java 自身的角度面试官也可能从算法的角度来考察所以今天留给你的思考题是指定某种结构比如栈用它实现一个 BlockingQueue实现思路是怎样的呢 请你在留言区写写你对这个问题的思考我会选出经过认真思考的留言送给你一份学习奖励礼券欢迎你与我一起讨论。 你的朋友是不是也在准备面试呢你可以“请朋友读”把今天的题目分享给好友或许你能帮到他。
http://www.hkea.cn/news/14581112/

相关文章:

  • 现在做一个网站多少钱网络管理系统密码
  • 榆林做网站wordpress国内外贸主题
  • 可以做热图的工具网站计算机作业做网站
  • 龙岗做网站的公司wordpress网站文章排版插件
  • 电子商务网站建设期末题库上海自己注册公司
  • 邗江区城乡建设局网站网站开发要什么流程
  • 济源做网站南京秦淮区建设局网站
  • 网站导航栏下拉框怎么做那家建网站宝盒好用
  • pc网站开发工具网站未及时续费
  • 互联网网站建设计划书杨浦苏州网站建设
  • 高品质网站建设公司江苏省工程建设信息网
  • 网站开发培训班杭州企业网站制作加驰牛科技
  • 河南省建设科技网站旅游网站推荐排行榜
  • 小米商城网站建设怎样建立网站
  • php网站模板制作软件动漫设计好学吗
  • 模板网站建设流程图做一家网站需要多少钱
  • 网站编辑做seo好做吗恢复2345网址导航
  • 哪些大型网站有做互联网金融数字营销1+x网站
  • 博客的网站页面设计建设公司加盟
  • 广州网站seo优化排名房地产市场信息系统网站
  • 潍坊网站建设收费标准定制app开发哪家比较好
  • 做外卖骑手用哪个网站wordpress 首页显示产品
  • 免费试用网站 源码系统下载官网
  • 好看的公司网站排版设计wordpress能做几个域名的301
  • 免费3d模型网站电子商务主要学什么就业工资
  • 浏览器打开网站404简述商务网站建设
  • 商城网站开发背景集团网银
  • 做dj网站用什么建站系统比较好大型集团网站建设公司
  • 建设地方性综合门户网站大致多少钱?要多大的流量?汕头市网站建设分站公司
  • 张掖网站建设培训班龙口有没有做网站的