当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:14:00  来源:本站整理

Java理论与实践: 并发调集类[Java编程]

赞助商链接



  本文“Java理论与实践: 并发调集类[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

在Java类库中呈现的第一个关联的调集类是 Hashtable ,它是JDK 1.0的一 部份. Hashtable 供应了一种易于利用的、线程安全的、关联的map功效,这当 然也是便利的.但是,线程安全性是凭代价换来的―― Hashtable 的全部办法 都是同步的.此时,无竞争的同步会招致可观的性能代价. Hashtable 的后继 者 HashMap 是作为JDK1.2中的调集框架的一部份呈现的,它通过供应一个差别 步的基类和一个同步的包装器 Collections.synchronizedMap ,办理了线程安 全性问题.通过将基本的功效从线程安全性中别脱离来, Collections.synchronizedMap 答应需求同步的用户可以拥有同步,而不需求同 步的用户则没必要为同步付出代价.

Hashtable 和 synchronizedMap 所采纳的得到同步的简单办法(同步 Hashtable 中大概同步的 Map 包装器对象中的每个办法)有两个主要的不足. 首先,这种办法关于可伸缩性是一种障碍,因为一次只能有一个线程可以拜候 hash表.同时,这样仍不足以供应真正的线程安全性,很多公用的混合操作仍旧 需求额外的同步.固然诸如 get() 和 put() 之类的简单操作可以在不需求额外 同步的情形下安全地完成,但还是有一些公用的操作序列,比方迭代大概put- if-absent(空则放入),需求外部的同步,以避免数据争用.

有条件的线程安全性

同步的调集包装器 synchronizedMap 和 synchronizedList ,有时也被称作 有条件地线程安全――全部单个的操作都是线程安全的,但是多个操作构成的操 作序列却大概招致数据争用,因为在操作序列中掌握流取决于前面操作的后果. 清单1中第一片段展示了公用的put-if-absent语句块――假如一个条目不在 Map 中,那么增添这个条目.不幸的是,在 containsKey() 办法返回到 put() 办法 被调用这段时间内,大概会有另一个线程也插入一个带有相同键的值.假如您想 确保只有一次插入,您需求用一个对 Map m 举行同步的同步块将这一对语句包 装起来.

清单1中其他的例子与迭代有关.在第一个例子中, List.size() 的后果在 循环的履行期间大概会变得无效,因为另一个线程可以从这个列表中删除条目. 假如机会不得当,在刚好进入循环的最后一次迭代之后有一个条目被另一个线程 删除了,则 List.get() 将返回 null ,而 doSomething() 则极大概会抛出一 个 NullPointerException 非常.那么,采纳什么办法才能避免这种情形呢?如 果当您正在迭代一个 List 时另一个线程也大概正在拜候这个 List ,那么在进 行迭代时您必须利用一个 synchronized 块将这个 List 包装起来,在 List 1 上同步,从而锁住整个 List .这样做固然办理了数据争用问题,但是在并发性 方面付出了更多的代价,因为在迭代期间锁住整个 List 会阻塞其他线程,使它 们在很长一段时间内不能拜候这个列表.

调集框架引入了迭代器,用于遍历一个列表大概其他调集,从而优化了对一 个调集合的元素举行迭代的历程.但是,在 java.util 调集类中实现的迭代器 极易崩溃,也就是说,假如在一个线程正在通过一个 Iterator 遍历集合时,另 一个线程也来改正这个调集,那么接下来的 Iterator.hasNext() 或 Iterator.next() 调用将抛出 ConcurrentModificationException 非常.就拿 方才这个例子来说,假如想要避免呈现 ConcurrentModificationException 异 常,那么当您正在举行迭代时,您必须利用一个在 List l 上同步的 synchronized 块将该 List 包装起来,从而锁住整个 List .(大概,您也可 以调用 List.toArray() ,在差别步的情形下对数组举行迭代,但是假如列表比 较大的话这样做代价很高).

清单 1. 同步的map中的公用竞争条件

Map m = Collections.synchronizedMap(new HashMap());
  List l = Collections.synchronizedList(new ArrayList());
  // put-if-absent idiom -- contains a race condition
  // may require external synchronization
  if (!map.containsKey(key))
   map.put(key, value);
  // ad-hoc iteration -- contains race conditions
  // may require external synchronization
  for (int i=0; i<list.size(); i++) {
   doSomething(list.get(i));
  }
  // normal iteration -- can throw ConcurrentModificationException
  // may require external synchronization
  for (Iterator i=list.iterator(); i.hasNext(); ) {
   doSomething(i.next());
  }

信任的错觉

synchronizedList 和 synchronizedMap 供应的有条件的线程安全性也带来 了一个隐患 ―― 开辟者会假定,因为这些调集都是同步的,所以它们都是线程 安全的,这样一来他们关于精确地同步混合操作这件事就会忽视.后来果是固然 表面上这些程序在负载较轻的时刻可以正常工作,但是一旦负载较重,它们就会 开始抛出 NullPointerException 或 ConcurrentModificationException .


  以上是“Java理论与实践: 并发调集类[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • 利用Javascript实现网页水印(非图片水印)
  • Java开辟环境的搭建
  • Ubuntu java安装与配置
  • 办理Ubuntu 10.04 Firefox3.6 Java浏览器插件不工作的问
  • Ubuntu重装后Java环境的设置
  • Sun Java进入Ubuntu 10.10软件中央
  • Ubuntu 10.10配置Java开辟环境
  • 在Ubuntu 10.10中配置Java环境变量的办法
  • Ubuntu下Java环境的搭建
  • Ubuntu 10.04 下安装 Java, JRE
  • Ubuntu 10.04下的搭建SUN JAVA开辟环境
  • Ubuntu 12.04安装java7
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .