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そうは言っても、2 人の異なる呼び出し元がキューから同じ結果を取得できる場合、キューに何か問題があります。

このコードを実行する正しい方法は、2 つの別個のリストを用意することです。1 つは などのリクエストの接続のキューで、もう 1 つは の接続externalClass.getConnection()のリストですPing。あなたのPing操作が何をしていても、外部クラスがその接続で行っていることに実際には影響を与えるべきではありませconnectionん.sql connectionPing

SELECT TOP 1 1

そして、それはあなたの接続が生きていることを意味します. 接続があまりにも長くアイドル状態であり、それ自体を閉じているため、これを実装している可能性が高いため..その場合、SQL dbmsのほとんどすべてのフレーバーが、まさにあなたがしようとしていることを行う接続プーリングをサポートしているため、実際にはすべきではありません。他の実行を待機させることにより、一度に Queue.Count を超える同時接続を防止したい場合を除きます (単純な などのオープン接続のプールを維持するよりもはるかに優れた方法で実行できますint counter) 。

異なるサーバーへの接続を維持し、複数のサーバー間でリクエストをローテーションしてアドホックな負荷分散を試みない限り、すべての接続のリストと利用可能な接続のキューで上記のソリューションを使用してください。このソリューションの主な利点は、アプリケーションが現在要求を処理している場合でも、アプリケーションを閉じるときにすべての接続を終了できることです。

しかし、あなたの質問に完全に答えるために:

循環ループがあった場合A -> B -> C -> A、次のようになります。各要素は、単に a の要素ではなく、リスト内の次の要素を指しqueueます。良い例は、サーバーAをpingし、サーバーBをpingし、サーバーをpingCA、次のように検出することです。

循環ループを検出する簡単な方法は、一度に 2 つ (または複数) の反復を実行することです。それらを X および Y と呼びます。

X を(またはコンテキスト内で) 2 回踏むたび.Ping()に、Y を 1 回踏むことになります。ping がループ内で何度も呼び出されないように、Visityour を呼び出すのではなく、などの新しいメソッドを作成することをお勧めします。Ping

キューが次のように見えると仮定しますA, B, C, A, B...

いくつかの手順の後、X は次のようになります。A, B, C, A一方、Y は のようになりますA, B履歴全体を保存するのではなく、現在の値のみを確認するため、X にステップインすると、新しい値が Y の現在の値と一致するかどうかを確認するため、最終的には常に衝突が発生します。

これは循環ループを検出するための最速または最も効率的な方法ではありませんが、最も単純であり、ループが一般的に小さい場合は、過去のルートの履歴リストを保存するよりも簡単です (場合によっては、コードに大幅な変更が必要になります)。 )。ループが 20 ステップを超える場合に使用できる、はるかに効率的なアルゴリズムがあります (複雑な分岐ツリーなどを処理するように設計されています)。この実装の最悪のケースは、素数のループ要素になることを認識することが重要です。

しかし、これをさらに拡張して 3ステップZごとに 1 回ステップするイテレーターを持つことで、平均してパフォーマンスを向上させることができます。新しい各イテレータの作成による素数)。XX

于 2012-04-25T05:24:23.407 に答える
0

たぶん私はあなたがそこで何をしているのか理解していませんでしたが、問題は外部タスクのようにPingタスクがエンキュー/デキュールールに従わないためだと思います。では、最初にPingタスクで接続をデキューし、その「ping値」を更新してから、エンキューし直してはどうでしょうか。

外部タスクが常に最小のping値で接続を取得することを保証することが目的の場合は、キューの代わりにヒープを使用することをお勧めします。

于 2012-04-25T23:43:40.430 に答える
0

ping は各マシンにのみ ping を送信しますか? それとも、あるマシンに ping を送信し、次のマシンに ping を送信し、次のマシンに ping を送信し、というように繰り返しますか?

これを解決する 1 つの方法は、すべてのマシンが既に ping されているかどうかを追跡することです。変更されていて、新しい ping を受信した場合、再度 ping を送信することはありません。

これを解決するもう 1 つの方法は、指定された ping パケットが既に認識されているマシンに関する情報を渡すことです。ping パケットが既に認識されているマシンに到達すると、そのパケットは終了します。

于 2012-04-24T21:33:17.737 に答える