接上一篇

java并发包小结(一)http://blog.csdn.net/aalansehaiyang52/article/details/8877579

Future 接口
Future 接口允许表示已经完成的任务、正在执行过程中的任务或者尚未开始执行的任务。通过 Future 接口,可以尝试取消尚未完成的任务,查询任务已经完成还是取消了,以及提取(或等待)任务的结果值。
FutureTask 类实现了 Future,并包含一些构造函数,允许将 Runnable 或 Callable(会产生结果的 Runnable)和 Future 接口封装。因为 FutureTask 也实现 Runnable,所以可以只将 FutureTask 提供给 Executor。一些提交方法(如 ExecutorService.submit())除了提交任务之外,还将返回 Future 接口。
Future.get() 方法获取任务计算的结果(或如果任务完成,但有异常,则抛出 ExecutionException)。如果任务尚未完成,那么 Future.get() 将被阻塞,直到任务完成;如果任务已经完成,那么它将立即返回结果。

使用 Future 构建缓存
该示例代码与 java.util.concurrent 中的多个类关联,突出显示了 Future 的功能。它实现缓存,使用 Future 描述缓存值,该值可能已经计算,或者可能在其他线程中'正在构造'。
它利用 ConcurrentHashMap 中的原子 putIfAbsent() 方法,确保仅有一个线程试图计算给定关键字的值。如果其他线程随后请求同一关键字的值,它仅能等待(通过 Future.get() 的帮助)第一个线程完成。因此两个线程不会计算相同的值。

  1. public class Cache {
  2. ConcurrentMap  map = new ConcurrentHashMap();
  3. Executor executor = Executors.newFixedThreadPool(8);
  4. public V get(final K key) {
  5. FutureTask f = map.get(key);
  6. if (f == null) {
  7. Callable c = new Callable() {
  8. public V call() {
  9. // return value associated with key
  10. }
  11. };
  12. f = new FutureTask(c);
  13. FutureTask old = map.putIfAbsent(key, f);
  14. if (old == null)
  15. executor.execute(f);
  16. else
  17. f = old;
  18. }
  19. return f.get();
  20. }
  21. }

Semaphore
Semaphore 类实现标准 Dijkstra 计数信号。计数信号可以认为具有一定数量的许可权,该许可权可以获得或释放。如果有剩余的许可权,acquire() 方法将成功,否则该方法将被阻塞,直到有可用的许可权(通过其他线程释放许可权)。线程一次可以获得多个许可权。
注意信号不跟踪哪个线程拥有多少许可权;这由应用程序来决定,以确保何时线程释放许可权,该信号表示其他线程拥有许可权或者正在释放许可权,以及其他线程知道它的许可权已释放。

CountdownLatch
CountdownLatch 类与 CyclicBarrier 相似,因为它的角色是对已经在它们中间分摊了问题的一组线程进行协调。它也是使用整型变量构造的,指明计数的初始值,但是与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。
其中,CyclicBarrier 是到达屏障的所有线程的大门,只有当所有线程都已经到达屏障或屏障被打破时,才允许这些线程通过,CountdownLatch 将到达和等待功能分离。任何线程都可以通过调用 countDown() 减少当前计数,这种不会阻塞线程,而只是减少计数。await() 方法的行为与 CyclicBarrier.await() 稍微有所不同,调用 await() 任何线程都会被阻塞,直到闩锁计数减少为零,在该点等待的所有线程才被释放,对 await() 的后续调用将立即返回。
当问题已经分解为许多部分,每个线程都被分配一部分计算时,CountdownLatch非常有用。在工作线程结束时,它们将减少计数,协调线程可以在闩锁处等待当前这一批计算结束,然后继续移至下一批计算。
相反地,具有计数 1 的 CountdownLatch 类可以用作'启动大门',来立即启动一组线程;工作线程可以在闩锁处等待,协调线程减少计数,从而立即释放所有工作线程。下例使用两个 CountdownLatche。一个作为启动大门,一个在所有工作线程结束时释放线程:

  1. class Driver { // ...
  2. void main() throws InterruptedException {
  3. CountDownLatch startSignal = new CountDownLatch(1);
  4. CountDownLatch doneSignal = new CountDownLatch(N);
  5. for (int i = 0; i < N; ++i) // create and start threads
  6. new Thread(new Worker(startSignal, doneSignal)).start();
  7. doSomethingElse();            // don't let them run yet
  8. startSignal.countDown();      // let all threads proceed
  9. doSomethingElse();
  10. doneSignal.await();           // wait for all to finish
  11. }
  12. }
  13. class Worker implements Runnable {
  14. private final CountDownLatch startSignal;
  15. private final CountDownLatch doneSignal;
  16. Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
  17. this.startSignal = startSignal;
  18. this.doneSignal = doneSignal;
  19. }
  20. public void run() {
  21. try {
  22. startSignal.await();
  23. doWork();
  24. doneSignal.countDown();
  25. } catch (InterruptedException ex) {} // return;
  26. }
  27. }

Hashtable 与 ConcurrentHashMap
作为可伸缩性的例子,ConcurrentHashMap 实现设计的可伸缩性要比其线程安全的上一代 Hashtable 的可伸缩性强得多。Hashtable 一次只允许一个线程访问 Map;ConcurrentHashMap 允许多个读者并发执行,读者与写入者并发执行,以及一些写入者并发执行。因此,如果许多线程频繁访问共享映射,使用 ConcurrentHashMap 的总的吞吐量要比使用 Hashtable 的好。
下表大致说明了 Hashtable 和 ConcurrentHashMap 之间的可伸缩性差别。在每次运行时,N 个线程并发执行紧密循环,它们从 Hashtable 或 ConcurrentHashMap 中检索随即关键字,60% 的失败检索将执行 put() 操作,2% 的成功检索执行 remove() 操作。测试在运行 Linux 的双处理器 Xeon 系统中执行。数据显示 10,000,000 个迭代的运行时间,对于 ConcurrentHashMap,标准化为一个线程的情况。可以看到直到许多线程,ConcurrentHashMap 的性能仍保持可伸缩性,而 Hashtable 的性能在出现锁定竞争时几乎立即下降。
与通常的服务器应用程序相比,这个测试中的线程数看起来很少。然而,因为每个线程未进行其他操作,仅是重复地选择使用该表,所以这样可以模拟在执行一些实际工作的情况下使用该表的大量线程的竞争。

线程 ConcurrentHashMap Hashtable
1 1.0 1.51
2 1.44 17.09
4 1.83 29.9
8 4.06 54.06
16 7.5 119.44
32 15.32 237.2

java并发包小结(二)的更多相关文章

  1. java并发包小结(一)

    java.util.concurrent 包含许多线程安全.高性能的并发构建块.换句话讲,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结构所执行的 ...

  2. 深入浅出Java并发包—锁机制(二)

    接上文<深入浅出Java并发包—锁机制(一)  >  2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tr ...

  3. Java并发包中常用类小结(一)

    从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来简单看一下相关的一些常见类的使用情况. 1.ConcurrentHashMap Concurre ...

  4. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  5. Java并发包源码学习之AQS框架(一)概述

    AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.con ...

  6. 深入浅出Java并发包—锁机制(三)

    接上文<深入浅出Java并发包—锁机制(二)>  由锁衍生的下一个对象是条件变量,这个对象的存在很大程度上是为了解决Object.wait/notify/notifyAll难以使用的问题. ...

  7. 深入浅出Java并发包—CAS机制

    在JDK1.5之前.Java主要靠synchronized这个关键字保证同步,已解决多线程下的线程不安全问题,但是这会导致锁的发生,会引发一些个性能问题. 锁主要存在一下问题 (1)在多线程竞争下,加 ...

  8. 对着java并发包写.net并发包之原子类型实现

    众所周知,java1.5并发包通过volatile+CAS原理提供了优雅的并发支持.今天仔细想想.net也有volatile关键字保证内存的可见性,同时也有Interlocked提供了CAS的API, ...

  9. Java SE之XML<二>XML DOM与SAX解析

    [文档整理系列] Java SE之XML<二>XML DOM与SAX解析 XML编程:CRUD(Create Read Update Delete) XML解析的两种常见方式: DOM(D ...

随机推荐

  1. EBS DBA指南笔记(一)

    第一章  ORACLE APPLICATIONS 的组件与架构 1.ebs组件的几大构成:客户端,form server,web server,concurrent processor,数据库.每个组 ...

  2. 【一天一道LeetCode】#85. Maximal Rectangle

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  3. 【一天一道LeetCode】#61. Rotate List

    一天一道LeetCode系列 (一)题目 Given a list, rotate the list to the right by k places, where k is non-negative ...

  4. 海量数据挖掘MMDS week1: Link Analysis - PageRank

    http://blog.csdn.net/pipisorry/article/details/48579435 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  5. python模块:调用系统命令模块subprocess等

    http://blog.csdn.net/pipisorry/article/details/46972171 Python经常被称作"胶水语言",因为它能够轻易地操作其他程序,轻 ...

  6. 怎样使用projectproperty sheet(.vsprops)来管理工程

    怎样使用projectproperty sheet(.vsprops)来管理工程 IDE:VS2005 前言 Project Property Sheet的意思是项目属性表,在大型项目中基本上都会使用 ...

  7. IP协议详解(转)

    本文转载自博文协议森林05 我尽力 (IP协议详解).这篇博文写的很有趣味,特转载! IPv4与IPv6头部的对比 我们已经在IP接力中介绍过,一个IP包分为头部(header)和数据(payload ...

  8. LIRe 源代码分析 6:检索(ImageSearcher)[以颜色布局为例]

    ===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...

  9. 系统性能监测(使用nmon、nmonanalyser)

    系统性能监测使用工具: l系统性能监测使用的主要监测工具是:nmon(AIX6.1及以上版本系统自带). l系统性能监测使用的主要分析工具是:nmonanalyser. NMON工具简介: NMON工 ...

  10. ERP-非财务人员的财务培训教(二)------如何评价公司/部门经营业绩

    一.财务比率分析 第一节  流动性比率 第二节  经营比率 第三节  资本结构比率 第四节  获利能力比率 第五节  现金流量比率 第六节  获现能力比率 二.财务比率金字塔 第二部分   如何评价公 ...