对于初学者,您没有循环。
循环是指你有一个指向自身的链表。您只有一个队列,当您单步执行它时,可能会有另一个线程将重复的元素添加到队列的末尾。
检测循环循环的方法是使用hashtable,在每个Ping()之前检查连接是否已经存在于连接中,如果存在,则继续移动到下一个元素,如果不存在'不存在然后你将它添加到hashtable 然后你调用你的Ping 操作到服务器。
或者您可以让您的初始ping 操作在该确切时间对队列进行快照,而不是越过它。
话虽如此,如果您可以让两个不同的呼叫者从队列中获得相同的A 结果,那么您的队列就有问题了。
执行此代码的正确方法是有两个单独的列表,一个是请求的连接队列,例如externalClass.getConnection(),另一个是Ping 的连接列表。无论您的Ping 操作在做什么,它都不应该影响任何外部类对其连接所做的任何事情,例如假设connection 是sql connection,那么Ping 应该执行如下操作:
SELECT TOP 1 1
仅此而已,这将意味着您的连接仍然存在。因为您可能会实施此操作,因为连接空闲时间过长并且会自行关闭。在这种情况下,您真的不应该这样做,因为几乎任何类型的 sql dbms 都支持连接池,这正是您想要做的。除非您想通过让其他执行等待来阻止多个 Queue.Count 并发连接(这本身可以更好地保持打开连接池,例如简单的int counter)
除非您保持与不同服务器的连接并尝试通过在多个服务器之间轮换请求来进行一些临时负载平衡,否则请使用我上面的解决方案以及所有连接列表和可用连接队列。此解决方案的主要好处是您可以在应用程序关闭时终止所有连接,即使它们当前正在处理请求。
但是,为了完整回答您的问题:
如果您确实有一个循环,它看起来像这样:A -> B -> C -> A,其中每个元素将指向列表中的下一个元素,而不仅仅是queue 中的元素。一个很好的例子是你 Ping server A which ping server B which ping server C which then 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 步时,可以使用更有效的算法(它们旨在处理复杂的分支树等)。重要的是要认识到这种实现的最坏情况将是循环元素的质数。
但是您可以通过进一步扩展它来提高平均性能@steps 或 7 等等(随着每个新迭代器的创建访问下一个递增的素数)。