多线程(三)

并发工具类和并发容器

 

为什么要使用ConcurrentHashMap

在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,HashMap在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表

形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。

HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法,其他线程也访问HashTable的同步方法时,会进入阻塞或轮询状态。如线程1使用put进行元素添加,线程2不但不能使用put方法添加元素,也不能使用get方法来获取元素,所以竞争越激烈效率越低。

一些有用的方法

很多时候我们希望在元素不存在时插入元素,我们一般会像下面那样写代码

synchronized(map){
   if (map.get(key) == null){
      return map.put(key, value);
   } else{
      return map.get(key);
   }
}

putIfAbsent(key,value)方法原子性的实现了同样的功能

V putIfAbsent(K key, V value)  

如果key对应的value不存在,则put进去,返回null。否则不put,返回已存在的value。  


boolean remove(Object key, Object value)  

如果key对应的值是value,则移除K-V,返回true。否则不移除,返回false。
boolean replace(K key, V oldValue, V newValue)  

如果key对应的当前值是oldValue,则替换为newValue,返回true。否则不替换,返回false。
public class UseChm {

	HashMap<String, String> hashMap = new HashMap<>();
	ConcurrentHashMap<String, String> chm = new ConcurrentHashMap<>();

	public String putIfAbsent(String key, String value) {
		int a;
		synchronized (hashMap) {
			if (hashMap.get(key) == null) {
				return hashMap.put(key, value);
			} else {
				return hashMap.get(key);
			}
		}
	}

	// 存值
	public String useChm(String key, String value) {
		return chm.putIfAbsent(key, value);
	}

}

Hash的解释

散列,任意长度的输入,通过一种算法,变换成固定长度的输出。属于压缩的映射。

Md5,Sha,取余都是散列算法,ConcurrentHashMap中是wang/jenkins算法

猜你喜欢

转载自my.oschina.net/u/3728166/blog/1824136