• 技术文章 >Java >java教程

    Java中Map实现线程安全的方式有哪些

    王林王林2023-04-19 19:52:04转载25

    方式1. 使用Hashtable

    Map<String,Object> hashtable=new Hashtable<String,Object>();

    这是所有人最先想到的,那为什么它是线程安全的?那就看看它的源码,我们可以看出我们常用的put,get,containsKey等方法都是同步的,所以它是线程安全的

    public synchronized boolean containsKey(Object key) {
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
                if ((e.hash == hash) && e.key.equals(key)) {
                    return true;
                }
            }
            return false;
        }
    
     public synchronized V get(Object key) {
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
                if ((e.hash == hash) && e.key.equals(key)) {
                    return (V)e.value;
                }
            }
            return null;
        }
         public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);
            return null;
        }

    其实现原理是在增删改查的方法上使用了synchronized锁机制,在多线程环境下,无论是读数据,还是修改数据,在同一时刻只能有一个线程在执行synchronize方法,因为是对整个表进行锁定。所以线程越多,对该map的竞争越激烈,效率越低,不推荐使用。

    方式2. 使用Collections.synchronizedMap(new Hashtable())

    其实现原理是使用工具类里面的静态方法,把传入进来的Hashtable包装成同步的,即在增删改查的方法上增加了synchronized所机制,其实现方式与Hashtable差不多,效率也差不多,不推荐使用。

    Map map = Collections.synchronizedMap(new Hashtable());

    以下是JDK源码

    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
            return new SynchronizedMap<>(m);
    }
    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();}
            }
            ......
        }

    方式3. 使用ConcurrentHashMap

    其实现原理是Hashtable是对整个表进行加锁,而ConcurrentHashMap是把表进行分段,初始情况下分成16段,每一段都有一把锁,当多个线程访问不同的段时,因为获取到的锁是不同的,所以可以并行的访问。效率比Hashtable高多了,推荐使用。

    以上就是Java中Map实现线程安全的方式有哪些的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:亿速云,如有侵犯,请联系admin@php.cn删除
    专题推荐:Java map
    上一篇:java中List中set方法和add方法的区别是什么 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • Java中如何使用transient关键字来控制序列化• Java实现树形结构的代码示例• Java并发编程之对象的共享实现方案• java类型擦除怎么应用• Java设计模式:模板方法模式实例解析
    1/1

    PHP中文网