有2种办法让HashMap线程安全,分别如下:
方法一:通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的。 这个要求大家习惯基于接口编程,因为返回的并不是HashMap,而是一个Map的实现。
方法二:重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap. 这个方法比方法一有了很大的改进。
有2种办法让HashMap线程安全,分别如下:
方法一:通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的。 这个要求大家习惯基于接口编程,因为返回的并不是HashMap,而是一个Map的实现。
方法二:重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap. 这个方法比方法一有了很大的改进。
直接用HashTable,HashTable线程安全。
我一般都会hashmap凡是在一个方法内部new并且不传到方法外面的基本上可以用hashmap,线程不安全的时候用currenthashmap。
比如类属性是map或者静态属性map而且会在不同的线程并发执行操作map时。
public class MapTest {
public static void main(String[] args) {
final Hashtable
map.put(1, "1");
new Thread(new Runnable() {
@Override
public void run() {
Enumeration
for (int i = 0; i < 5; i++) {
iterator = map.elements();
map.put(i, i + "");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(MapTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(iterator.nextElement());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Enumeration
for (int i = 0; i < 5; i++) {
iterator = map.elements();
map.put(i, i + "");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(MapTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(iterator.nextElement());
}
}
}).start();
}
}
这是没有异常代码
public class MapTest {
public static void main(String[] args) {
final Hashtable
map.put(1, "1");
new Thread(new Runnable() {
@Override
public void run() {
Iterator
for (int i = 0; i < 5; i++) {
iterator = map.keySet().iterator();
map.put(i, i + "");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(MapTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(iterator.next());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Iterator
for (int i = 0; i < 5; i++) {
iterator = map.keySet().iterator();
map.put(i, i + "");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(MapTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(iterator.next());
}
}
}).start();
}
}
这里是有异常代码,Iterator 时产生异常的主要原因,Iterator创建的时候会拿到创建时容器的容量,一个整形数据。 读取的时候就拿这个容量数据先去检查是不是和当前实际容量相等,如果不相等就ConcurrentModificationException异常,相等就开始读数据,所谓线程安全就是一个线程在使用Iterator 读数据的时候,另外线程往里加数据,结果就出现Iterator 保存的容器容量和当前实际容量不等了,就不安全了。
而在hashtable中使用了Enumeration这个线程安全的对象,就是说在另外的线程里加东西的时候他会知道当前容器已经改变,所以使用他是线程安全的。
如果楼主还不明白去开下源代码就知道了。
在周二面试时,一面的面试官有问到HashMap是否是线程安全的,如何在线程安全的前提下使用HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap和synchronized
Map的原理和区别。当时有些紧张只是简单说了下HashMap不是线程安全的;Hashtable线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁;而ConcurrentHashMap不仅线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术。当时忘记了synchronized
Map和解释一下HashMap为什么线程不安全。面试结束后问了下面试官哪里有些不足,面试官说上面这个问题的回答算过关,但可以在深入一些或者自己动手尝试一下。so~~~虽然拿到了offer,但还是再整理一下,不能得过且过啊。