当运行以下类ExecutionService往往会死锁。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorTest {
public static void main(final String[] args) throws InterruptedException {
final ExecutorService executor = Executors.newFixedThreadPool(10);
final HashMap<Object, Object> map = new HashMap<Object, Object>();
final Collection<Callable<Object>> actions = new ArrayList<Callable<Object>>();
int i = 0;
while (i++ < 1000) {
final Object o = new Object();
actions.add(new Callable<Object>() {
public Object call() throws Exception {
map.put(o, o);
return null;
}
});
actions.add(new Callable<Object>() {
public Object call() throws Exception {
map.put(new Object(), o);
return null;
}
});
actions.add(new Callable<Object>() {
public Object call() throws Exception {
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
iterator.next();
}
return null;
}
});
}
executor.invokeAll(actions);
System.exit(0);
}
}
那么,为什么会出现这种情况? 或者更好的是 - 我怎么能写一个测试,以确保一个自定义的抽象地图的实现是线程安全的吗? (有些实现有多个地图,另一种委托给高速缓存执行等)
一些背景:发生这种情况的Java 1.6.0_04和1.6.0_07在Windows上。 我知道,这个问题是来自sun.misc.Unsafe.park():
- 我可以重现这个问题上我的酷睿双核2.4GHz的笔记本电脑,但不能同时运行调试
- 我可以在工作中对我的酷睿2四核调试,但我已经把它挂在RDP,所以将无法得到一个堆栈跟踪到明天
下面大多数的答案是关于HashMap中的非线程安全的,但我能找到的HashMap没有锁定线程 - 这是所有在ExecutionService代码(和Unsafe.park())。 我会仔细检查线程明天。
这一切都是因为一个自定义的抽象地图实现不是线程安全的,所以我开始着手确保所有的实现是线程安全的。 从本质上说,我想确保我的ConcurrentHashMap等的理解是正是我期待的,但已经找到了ExecutionService是奇怪的缺乏......