0

我有一个并发的连接队列。有一个 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 过并且应该完成当前执行。

4

3 回答 3

1

对于初学者,您没有循环。

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

检测循环循环的方法是使用hashtable, 在每次Ping()检查连接中是否已经存在连接之前,如果存在,则继续移动到下一个元素,如果不存在,则将其添加到hashtable然后你调用你的Ping操作到服务器。

或者你可以让你的初始ping操作在那个确切的时间制作队列的快照,而不是越过它。

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

执行此代码的正确方法是有两个单独的列表,一个是请求的连接队列,例如,externalClass.getConnection()另一个是连接的列表Ping。无论您的Ping操作在做什么,它都不应该影响任何外部类对其连接所做的任何事情,例如假设connection是 a sql connectionthenPing应该执行如下操作:

SELECT TOP 1 1

仅此而已,这将意味着您的连接仍然存在。因为您可能会实施此操作,因为连接空闲时间过长并且会自行关闭。在这种情况下,您真的不应该这样做,因为几乎任何类型的 sql dbms 都支持连接池,这正是您想要做的。除非您想通过让其他执行等待来阻止超过 Queue.Count 的并发连接(这本身可以通过更好的方式来保持打开的连接池,例如简单的int counter

除非您保持与不同服务器的连接并尝试通过在多个服务器之间轮换请求来进行一些临时负载平衡,否则请使用我上面的解决方案以及所有连接列表和可用连接队列。此解决方案的主要好处是您可以在应用程序关闭时终止所有连接,即使它们当前正在处理请求。

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

如果你确实有一个循环,它看起来像这样:A -> B -> C -> A每个元素都指向列表中的下一个元素,而不仅仅是 a 中的元素queue。一个很好的例子是你 Ping 服务器A,它 ping 服务器B,它 ping 服务器C,然后 ping A,你会按如下方式检测它:

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

每第二次踏出(或.Ping()在您的上下文中)X,您就会踏出一次 Y。您可能想要创建一个新方法,Visit而不是调用您的方法,Ping以便在循环中不会多次调用 ping。

假设队列看起来像A, B, C, A, B...

几个步骤后 X 看起来像:A, B, C, A而 Y 看起来像A, B。您所做的是您存储整个历史记录,您只查看当前值,因此当您进入 X 时,您会检查新值是否与 Y 的当前值匹配,因此我们最终总会遇到冲突。

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

但是您可以通过进一步扩展它来提高平均性能,使其具有一个Z每三个X步骤执行一次的迭代器,此时实际上不值得添加一个每 5X步或 7 步执行一次的额外迭代器,依此类推(访问下一个增量质数与每个新迭代器的创建)。

于 2012-04-25T05:24:23.407 回答
0

也许我不明白你在那里做什么,但对我来说,问题似乎是因为 Ping 任务没有像外部任务那样遵循入队/出队规则。那么让 Ping 任务先出队一个连接,刷新它的“ping 值”,然后再入队呢?

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

于 2012-04-25T23:43:40.430 回答
0

您的 ping 是只 ping 每台机器,还是 ping 一台机器,哪台 ping 下一台,哪台 ping 下一台,然后以此类推?

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

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

于 2012-04-24T21:33:17.737 回答