在以下代码段中,我尝试使用Hashtable
,即所谓的线程安全和HashMap
。但在这两种情况下我都会ConcurrentModificationExceptionn
。如果是这样,那么在线程安全的情况下HashTable
优于HashMap
的优势
public class multiThreadedEnv {
static Map<Integer, String> map = new Hashtable<Integer, String>();
//static Map<Integer, String> map = new HashMap<Integer, String>();
static{
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.put(4, "Four");
map.put(5, "Five");
}
public static void main(String[] args) {
Thread t1 = new Thread(){
public void run() {
Iterator itr= map.entrySet().iterator();
while(itr.hasNext()){
Entry<String,String> entry=(Entry<String, String>) itr.next();
System.out.println(entry.getKey()+" , "+entry.getValue());
itr.remove();
Thread.sleep(2000);
}
}
};
Thread t2= new Thread(){
public void run() {
Iterator itr= map.entrySet().iterator();
while(itr.hasNext()) {
Entry<String,String> entry=(Entry<String, String>) itr.next();
System.out.println(entry.getKey()+" , "+entry.getValue());
itr.remove();
Thread.sleep(2000);
}
}
};
t1.start();
t2.start();
}
}
答案 0 :(得分:1)
Hashtable
已同步,阻止两个线程同时访问它。
从Java 2平台v1.2开始,该类被改进以实现
Map
接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Hashtable
是同步的。如果不需要线程安全实现,建议使用HashMap
代替Hashtable
。如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap
代替Hashtable
。
HashMap
未同步。
请注意,此实现未同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)
同步不会阻止ConcurrentModificationException
,因为他们都说:
所有这类&#34;集合视图方法返回的迭代器&#34; fail-fast :如果在创建迭代器之后的任何时候对[Hashtable / map]进行结构修改,除了通过迭代器自己的
remove
方法之外,迭代器将抛出ConcurrentModificationException
。
请注意,单个线程可以通过直接更新Hashtable / HashMap同时迭代它来导致ConcurrentModificationException
。它并不需要多线程来违反这条规则。
Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。他们不抛出
ConcurrentModificationException
。但是,迭代器设计为一次只能由一个线程使用。
因此,HashMap
对单线程访问很有用
Hashtable
对于多线程访问很有用,只要他们不需要迭代地图。
ConcurrentHashMap
允许多个线程进行更新和迭代。