Java 5.0 adds ConcurrentHashMap, a replacement for synchronized hash-based Map implementations, and CopyOnWriteArrayList, a replacement for synchronized List implementations for cases where traversal is the dominant operation. The new ConcurrentMap interface adds support for common compound actions such as put-if-absent, replace, and conditional remove.

Java 5.0 also adds two new collection types, Queue and BlockingQueue. A Queue is intended to hold a set of elements temporarily while they await processing. Several implementations are provided, including ConcurrentLinkedQueue, a traditional FIFO queue, and PriorityQueue, a (non concurrent) priority ordered queue.

Java 6 adds ConcurrentSkipListMap and ConcurrentSkipListSet, which are concurrent replacements for a synchronized SortedMap or SortedSet (such as treeMap or TReeSet wrapped with synchronizedMap).

首先我们说,替换同步hashMap的实现的concurrentHashMap,例如hashTable,写到这里突然想到了一个面试题:

在不使用锁的情况下,怎么样使hashMap 的size()方法变为线程安全的? (这个也就是要你明白ConcurrentHashMap的源码的话,就比较的容易的明白面试官要问的是什么内容)

另外还有一个比较重要的事情:

concurrentHashMap 提供的size(),isEmpty() 都是近似的精确的值,并不是完全的正确的值,这也符合并发编程环境的语意。

具体是怎么实现的,我们可以看到源码中是这样描述的:

http://www.iteye.com/topic/1103980

http://www.iteye.com/topic/344876

说的比较的详细:hashmap 被分为了segment,然后在不同的segment上面进行加锁,操作。

ConcurrentHashMap的size操作也采用了一种比较巧的方式,来尽量避免对所有的Segment都加锁。前面我们提到了一个Segment中的有一个modCount变量,代表的是对Segment中元素的数量造成影响的操作的次数,这个值只增不减,size操作就是遍历了两次Segment,每次记录Segment的modCount值,然后将两次的modCount进行比较,如果相同,则表示期间没有发生过写入操作,就将原先遍历的结果返回,如果不相同,则把这个过程再重复做一次,如果再不相同,则就需要将所有的Segment都锁住,然后一个一个遍历了。

public int size() {
// Try a few times to get accurate count. On failure due to
// continuous async changes in table, resort to locking.
final Segment<K,V>[] segments = this.segments;
int size;
boolean overflow; // true if size overflows 32 bits
long sum; // sum of modCounts
long last = 0L; // previous sum
int retries = -1; // first iteration isn't retry
try {
for (;;) {
if (retries++ == RETRIES_BEFORE_LOCK) {
for (int j = 0; j < segments.length; ++j)
ensureSegment(j).lock(); // force creation
}
sum = 0L;
size = 0;
overflow = false;
for (int j = 0; j < segments.length; ++j) {
Segment<K,V> seg = segmentAt(segments, j);
if (seg != null) {
sum += seg.modCount;
int c = seg.count;
if (c < 0 || (size += c) < 0)
overflow = true;
}
}
if (sum == last)
break;
last = sum;
}
} finally {
if (retries > RETRIES_BEFORE_LOCK) {
for (int j = 0; j < segments.length; ++j)
segmentAt(segments, j).unlock();
}
}
return overflow ? Integer.MAX_VALUE : size;
}

这个可以对应上面的那个面试题。

再说这个CopyOnWriteArray适合的场景是:CopyOnWriteArrayList适合使用在读操作远远大于写操作的场景里,比如缓存。发生修改时候做copy,新老版本分离,保证读的高性能,适用于以读为主的情况。

笔记:java并发编程实践1的更多相关文章

  1. [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍

    阅读<Java并发编程实践>一书后整理的思维导图.

  2. [Java 并发] Java并发编程实践 思维导图 - 第二章 线程安全性

    依据<Java并发编程实践>一书整理的思维导图.

  3. 读Java并发编程实践中,向已有线程安全类添加功能--客户端加锁实现示例

    在Java并发编程实践中4.4中提到向客户端加锁的方法.此为验证示例,写的不好,但可以看出结果来. package com.blackbread.test; import java.util.Arra ...

  4. [Java 并发] Java并发编程实践 思维导图 - 第四章 对象的组合

    依据<Java并发编程实践>一书整理的思维导图. 第一部分: 第二部分:

  5. Java并发编程实践

    最近阅读了<Java并发编程实践>这本书,总结了一下几个相关的知识点. 线程安全 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任 ...

  6. java并发编程实践笔记

    文章转自:http://kenwublog.com/java-concurrency-in-practise-note 1, 保证线程安全的三种方法 :a, 不要跨线程访问共享变量b, 使共享变量是 ...

  7. 读书笔记-----Java并发编程实战(一)线程安全性

    线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet @ThreadSafe public class StatelessFactorizer ...

  8. Java 并发编程实践基础 读书笔记: 第三章 使用 JDK 并发包构建程序

    一,JDK并发包实际上就是指java.util.concurrent包里面的那些类和接口等 主要分为以下几类: 1,原子量:2,并发集合:3,同步器:4,可重入锁:5,线程池 二,原子量 原子变量主要 ...

  9. Java 并发编程实践基础 读书笔记: 第一章 JAVA并发编程实践基础

    1.创建线程的方式: /** * StudySjms * <p> * Created by haozb on 2018/2/28. */ public class ThreadDemo e ...

随机推荐

  1. Machine Learning—Mixtures of Gaussians and the EM algorithm

    印象笔记同步分享:Machine Learning-Mixtures of Gaussians and the EM algorithm

  2. HDFS集群balance(2)-- 架构概览

    转载请注明博客地址:http://blog.csdn.net/suileisl HDFS集群balance,对应版本balance design 6 如需word版本,请QQ522173163联系索要 ...

  3. 从零开始写一个Tomcat(壹)

    Tomcat是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,也是一个servlet容器的优秀解决方案,做Java web开发的基本上都使用过,但是tomcat大多时间对于我们是一个黑 ...

  4. Android Back Home键监听

    Android Back Home键监听 Back键的监听 对于Back键的监听比较容易,可以在多个系统回调处拦截,比如在activity的下列方法中都可以收到Back键按下的事件: @Overrid ...

  5. JAVA通过url获取页面内容

    String address = "http://sports.sina.com.cn/nba/live.html?id=2015050405"; URL url = new UR ...

  6. smokeping报错Can't locate RRDs.pm in @INC (@INC contains

    安装完smokeping,执行debug语句: ./bin/smokeping --debug-daemon ,提示如下错误: Can't locate RRDs.pm in @INC (@INC c ...

  7. PHP 开发工具【2】

    关于PHP的开发工具其实网站上可以搜索到非常多,对于初学者来说,太多的选择反而不知道怎么去选. 本文是基于window平台上,针对PHP初学者定制了一套非常好用的开发工具. PHP开发工具其实包括以下 ...

  8. GET方式,获取服务器文件

    package com.http.get; import java.io.FileOutputStream; import java.io.IOException; import java.io.In ...

  9. R2:获取一个event_base

    原文链接:http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html 创建一个event_base 在你使用任何有意思的Libeve ...

  10. 自定义窗口 mfc

    typedef struct _WNDCLASS { UINT style; //制定窗口的类型 WNDPROC lpfnWndProc; int cbClsExtra; //额外的数值 int cb ...