java正在遍历队列的concurrentHashMap,以查看是否所有队列都是空的,而其他线程可能会添加到队列中
这是一个非常具体的问题,但我们已经被困了一段时间,我在网站上搜索了一个答案,但没有找到(有史以来第一次!)。现在我们开始:
我的数据结构是concurrentHashMap。映射中的每个值都是Actions的ConcurrentLinkedQue(这是我编写的一个抽象类,由几个Actions扩展而成,与问题实际上无关)。队列被昵称为“演员”
基本程序流程是:
有一系列线程。每个线程都会遍历哈希映射,寻找要执行的操作。如果操作队列为空,线程将移动到下一个队列。如果它找到一个操作,线程将从队列中弹出它并执行该操作。只有在之前的所有操作都完成的情况下,新操作才会在程序运行时分批提交到队列
如果所有队列都是空的,会发生什么? 我们希望避免“忙等待”,因此如果所有队列都为空,线程将进入睡眠状态。它什么时候醒来?我们有一个“版本监视器”,它基本上统计程序中添加了多少操作。这些线睡在这个柜台上
提交给计划的新行动-->;版本计数器增加一-->;线程醒来
我们如何知道是否所有队列都是空的?好吧,这是一个很好的老方法——我们迭代它们,每次都检查“isEmpty”,同时保持一个“isAllEmpty”布尔值
这就是我们的问题场景:
-所有队列都是空的。 -线程遍历所有队列,查看它们是否为空。 -在线程已经检查了某个队列之后,将向该队列提交一个新操作
事情是这样的:线程认为所有队列都是空的,所以他就睡觉了。他错过了“叫醒电话”(版本号增加了一个),因为当时他没有睡觉(而是在队列中重复)。不会向程序提交进一步的操作,因为旧的一批操作尚未完成。线程等待新操作,操作等待线程。僵局
我们如何避免这种情况?我们认为使用ConcurrentHashMap应该可以解决这个问题,但显然,遍历它们是不安全的。我们根本不允许使用synchronized。我们只是不知道如何修复它
我知道,随着线程数量的增加,这个问题变得不太可能,但我们也需要能够使用少量线程运行——即使只有一个。对于一个线程,这种情况经常发生。你有什么建议吗
以下是一些相关代码:
while (!Thread.currentThread().isInterrupted())
{
if(actors.isEmpty())
//if there's no actors, we need to wait until new actor will added to the hash map
{
try {
vm.await(vm.getVersion());//waits until the version monitor will be changed
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
}
//check if all queues are empty
boolean isAllEmpty = true;
Iterator <ConcurrentHashMap.Entry<String, QueuePair>> it2 = actors.entrySet().iterator();
while (it2.hasNext() && isAllEmpty){
if (!it2.next().getValue().queue.isEmpty())
isAllEmpty=false;
}
if(isAllEmpty)//all actors are empty
{
try {
vm.await(vm.getVersion());//waits until the version monitor will be changed
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
}
Iterator <ConcurrentHashMap.Entry<String, QueuePair>>it = actors.entrySet().iterator();
while (it.hasNext())//if there is an available actors queue, execute one of it actions
{
//irrelevant code that executes the action
}
}
}
});
谢谢回答:)
共 (0) 个答案