方式1. 使用hashtablemap<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实现线程安全的方式有哪些的详细内容。