检测并发队列中的循环循环

时间:2012-04-24 20:42:05

标签: algorithm concurrency queue

我有一个并发的连接队列。有一个ping任务定期通过队列中的所有可用连接来执行ping,同时应用程序可以从队列中请求连接以供其使用。

检测循环循环以便ping任务可以完成当前执行的好方法是什么?

修改

示例:假设并发队列具有连接A,B和C.

有一个ping任务遍历队列。因此,在此示例中,它将A.ping()B.ping()C.ping()。现在有一个外部类,它也请求队列连接,而ping任务也在队列上迭代。因此,假设A.ping()已完成,externalClass.getConnection()将返回A。当ping任务完成C.ping()时,externalClass.releaseConnection(A)发生。现在队列的顺序是B,C and A。因此ping任务在完成C.ping()之后将再次找到A,此时任务必须决定A已经被ping并且应该完成当前执行。

3 个答案:

答案 0 :(得分:1)

首先,你没有循环循环。

循环循环是指有一个指向自身的链表。您只有一个队列,当您单步执行它时,可能有另一个线程将重复的元素添加到队列的末尾。

检测循环循环的方法是使用hashtable,在每个Ping()之前检查连接中是否已存在连接,如果确实存在,则只需转到下一个元素,如果它不存在,则将其添加到hashtable,然后将Ping操作调用到服务器。

或者您可以让您的初始ping操作在该确切时间创建队列快照,而不是跨越它。

话虽如此,如果您可以让两个不同的呼叫者从队列中获得相同的A结果,那么您的队列会出现问题。

执行此代码的正确方法是拥有两个单独的列表,一个是externalClass.getConnection()等请求的连接队列,另一个是Ping的连接列表。无论你的Ping操作是做什么的,它都不应该影响任何外部类使用它的连接做的任何事情,例如假设connectionsql connection,那么Ping应该执行像这样的东西:

SELECT TOP 1 1

仅此而已,这将意味着你的联系仍然存在。因为您可能正在实现这一点,因为连接空闲时间过长并自行关闭..在这种情况下,您确实不应该这样做,因为几乎所有sql dbms都支持连接池,这正是您正在尝试做的事情。除非您希望通过让其他执行等待来同时阻止多个Queue.Count并发连接(这本身可以做更好的方式来保持打开的连接池,例如简单的int counter

除非您保持与不同服务器的连接并尝试通过跨多个服务器轮换请求来进行某些特殊负载平衡,否则请使用我的上述解决方案,其中包含所有连接列表和可用连接队列。此解决方案的主要好处是,即使应用程序正在处理请求,您也可以在应用程序关闭时终止所有连接。

但是,为了完整回答您的问题:

如果确实有一个循环循环,它将如下所示:A -> B -> C -> A其中每个元素指向列表中的下一个,而不仅仅是{{1}中的元素}。一个很好的例子是Ping服务器queue ping服务器A,它ping服务器B然后ping C,你将检测到它如下:

检测循环循环的简单方法是一次运行两次(或多次)迭代,我们称之为X和Y.

每走一步(或在你的上下文中A)X,你就一步一步。您可能想要创建一个新方法,例如.Ping(),而不是调用Visit,以便在循环内不多次调用ping。

假设队列看起来像Ping

经过几个步骤后,X看起来像:A, B, C, A, B...,而Y看起来像A, B, C, A。你做的是你存储整个历史记录,你只看当前值,所以当你进入X时你检查新值是否与Y的当前值匹配,因此我们将最终总是发生碰撞。

这不是检测循环循环的最快或最有效的方法,但它是最简单的,如果您的循环通常很小,则比存储过去路径的历史列表(在某些情况下需要显着)更容易对代码的更改)。当你的循环超过20步(它们被设计用于处理复杂的分支树等)时,可以使用更高效的算法。重要的是要认识到这种实现的最坏情况将是大量的循环元素。

但是你可以通过进一步扩展这一点来平均提高性能,以便有一个A, B迭代器,每三步Z步进一次,此时不值得添加一个步骤每5个X步或7个等等(通过创建每个新迭代器访问下一个增量素数)。

答案 1 :(得分:0)

你的ping只ping每台机器,还是ping一台机器,ping下一台机器,ping下一台机器,然后等等?

解决这个问题的一种方法是让每台机器都跟踪它是否已被ping。如果已经,并且它收到新的ping,则它不会再次发送ping。

解决此问题的另一种方法是传递有关给定ping数据包已经看到的机器的信息,并且当ping数据包到达已经看到的机器时,它将终止。

答案 2 :(得分:0)

也许我不明白你在那里做了什么,但对我来说看起来问题是因为Ping任务不像外部任务那样遵循入队/出队规则。那么如何让Ping任务首先使连接出列,刷新其“ping值”然后将其排队?

如果您的目标是保证外部任务始终获得具有最小ping值的连接,那么您可能希望使用堆而不是队列。