美文网首页
如何线程安全的使用HashMap

如何线程安全的使用HashMap

作者: Sophia_dd35 | 来源:发表于2019-07-20 23:51 被阅读0次

实现线程安全的方式有三种,分别是使用HashTableCollections.SynchronizeMapConcurrentHashMap

一、HashTable

Hashtable 源码中是使用 synchronized 来保证线程安全的,比如下面的 get 方法和 put 等方法:

public synchronized V put(K key, V value) { ... }
public synchronized V get(Object key) { ... }
public synchronized int size(Object key) { ... }
public synchronized boolean isEmpty() { ... }
public synchronized V remove(Object key) { ... }
public synchronized void putAll(Map<? extends K, ? extends V> t) { ... }
...

所以当一个线程访问 HashTable 的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。因此Hashtable效率很低,基本被废弃。。

二、SynchronizedMap

SynchronizedMap是Collectionis的内部类

//使用方法
Map m = Collections.synchronizedMap(new HashMap());

//源码部分
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }
 /** 
     * @serial include
     */
    private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;

        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize

        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }

        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }

        private transient Set<K> keySet;
        private transient Set<Map.Entry<K,V>> entrySet;
        private transient Collection<V> values;

Collections.synchronizedMap()和Hashtable一样,实现上在调用map所有方法时,都对整个map进行同步。效率还是硬伤。

三、ConcurrentHashMap

ConcurrentHashMap使用分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问,极大提升了效率。相关源码敬请期待!

四、三者的效率对比

分别通过三种方式创建 Map 对象,使用 ExecutorService 来并发运行5个线程,每个线程添加/获取500K个元素,比较其用时多少。

System.out: Test started for: class java.util.Hashtable
System.out: 500K entried added/retrieved in 92962 ms
System.out: 500K entried added/retrieved in 92199 ms
System.out: 500K entried added/retrieved in 92549 ms
System.out: 500K entried added/retrieved in 93331 ms
System.out: 500K entried added/retrieved in 92387 ms
System.out: For class java.util.Hashtable the average time is 92685 ms
System.out: Test started for: class java.util.Collections$SynchronizedMap
System.out: 500K entried added/retrieved in 99217 ms
System.out: 500K entried added/retrieved in 99487 ms
System.out: 500K entried added/retrieved in 100437 ms
System.out: 500K entried added/retrieved in 99606 ms
System.out: 500K entried added/retrieved in 100804 ms
System.out: For class java.util.Collections$SynchronizedMap the average time is 99910 ms
System.out: Test started for: class java.util.concurrent.ConcurrentHashMap
System.out: 500K entried added/retrieved in 10360 ms
System.out: 500K entried added/retrieved in 9359 ms
System.out: 500K entried added/retrieved in 8621 ms
System.out: 500K entried added/retrieved in 9833 ms
System.out: 500K entried added/retrieved in 9964 ms
System.out: For class java.util.concurrent.ConcurrentHashMap the average time is 9627 ms

相关文章

网友评论

      本文标题:如何线程安全的使用HashMap

      本文链接:https://www.haomeiwen.com/subject/jwtplctx.html