【发布时间】:2012-12-18 05:53:07
【问题描述】:
我有一个集合,我想产生一些线程来对其元素做一些繁重的工作。集合的每个元素都必须被处理一次,并且只处理一次。我想尽可能少地保持同步,我想出了以下代码:
//getting the iterator is actually more complicated in my specific case
final Iterator it = myCollection.terator();
Thread[] threads = new Thread[numThreads];
for( int i = 0; i < numThreads; i++ ) {
threads[i] = new Thread(new Runnable() {
public void run() {
Object obj = null;
while(true) {
synchronized (it) {
if(it.hasNext())
obj = it.next();
else
return;
}
//Do stuff with obj
}
}
});
threads[i].start();
}
for (Thread t : threads)
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
注意:在“使用 obj 做事”时,任何线程都不会通过添加或删除项目来修改集合
这段代码与我发现的示例完全不同,在这些示例中人们倾向于在集合本身上进行同步,使用Collection.synchronizedStuff..,或者他们只是在整个迭代中同步。在我的研究中,我还发现了使用 ThreadPoolExecutor 实现的可能更好的替代方案,但让我们暂时忘记它......
考虑到上面的注释 1,上面的代码安全吗?如果不是,为什么?
【问题讨论】:
-
只要注释 1 保持正确就可以了。不过,执行者绝对是解决此类问题的方法。
-
如果您出于性能原因尝试将
synchronized块保持较小,那么您可能会惊讶于在创建和执行每个(本机)线程期间花费了多少时间,请按照建议使用执行程序. -
您的概念代码看起来不错。应该很好用。对迭代器的访问(包括检查和读取对象)是同步的,所以没有问题。
标签: java multithreading iterator