我试图测试关于跨多个线程共享的迭代器的一些事情。我写了一个非常简单(而且非常愚蠢)的程序,它应该在不同的线程中迭代相同的映射。这是代码:
final Map<Integer, Integer> m = new HashMap<Integer, Integer>();
final Random r = new Random();
for(int i = 0; i< 1000 ; i++){
m.put(r.nextInt(10000), r.nextInt(10000));
}
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Iterator<Integer> it = m.keySet().iterator();
it.next();
for(Integer i : m.keySet()){
System.out.println("T1 " + i);
try {
Thread.sleep(r.nextInt(100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Iterator<Integer> it = m.keySet().iterator();
it.next();
for(Integer i : m.keySet()){
System.out.println("T2 " + i);
try {
Thread.sleep(r.nextInt(100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t1.run();
t2.run();
现在,当我运行这个时,我希望得到某种并发修改的异常,或者在控制台中混合使用“T1”和“T2”消息。会发生什么是我的程序从线程1的映射输出所有值,然后THEN进入线程2.为什么这种可序列化行为就是这里的情况?
答案 0 :(得分:6)
您需要致电t1.start()
和t2.start()
而不是run
。
致电run
只会执行run
方法中的代码
start
是启动新线程的原因。
答案 1 :(得分:2)
您正在单个线程(主线程)中执行操作,因为您正在执行t.run()而不是t.start()。
话虽如此,请注意使用两个线程并不总是导致交错执行;通常按顺序执行操作更有效,因此JVM按顺序调度实际操作。
此外,标准哈希映射的并发修改检测是最好的努力,并不是一种保证机制。