有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案