0

SNMP コマンドを送信し、トラップをリッスンするプログラムがあります。

私の最初の方法は、SNMP の送信を調整します。彼が送信を完了したら、トラップを受信したという通知を受信するまで待って、実行を継続できるようにする必要があります。現在、グローバル オブジェクトを同期することでそれを実行しようとしていますが、うまくいかず、それが私にとって理想的な解決策であるかどうかはわかりません。

public synchronized int loginUser(ScopedPDU pdu) throws IOException
{

    loginUserManager = new LoginUserManager();

    pdu = buildPdu();   

// send command
        errorStatus = snmpManager.snmpSend(pdu);

        if (errorStatus == SnmpManager.SNMP_PASS)
        {
            // Wait for traps
            synchronized(syncObject)
            {
// read global variable status to see if it's no longer in progress
                while(status == TrapStatus.INPROGRESS)
                {
                    try {
                        System.out.println("Waiting for login to be done");
                        syncObject.wait();
                        System.out.println("We received a notify");
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        } //(errorStatus == SnmpManager.SNMP_PASS)
        else
        {
            return TrapStatus.FAIL;
        }

    System.out.println("Returning status");
    return status;

}

私の 2 番目の方法はトラップを受信し (そして最初の方法とは別のスレッドで実行され)、必要な正しいステータスを取得していますが、他のスレッドに通知することはできません。

public synchronized void readTrap(Vector v)
{
    Enumeration e = v.elements();

    if(v.contains(PduTrap.UserLoginStatusTrap))
    {
// gets status of login
        status = loginUserManager.getStatus(e);

        synchronized(syncObject)
        {
// notify first method to read the new status
            syncObject.notify();            
        }
    }
        }

status と SyncObject は、スレッド間で共有しようとしているグローバル タイプです。クラス コンストラクターでステータスを INPROGRESS に初期化します。

private int status;
private Object syncObject;  

なぜ物事がうまくいかないのか、または私がこれを完全に間違った方法で行っているのか、誰か教えていただけますか? 現在、私の loginUser メソッドは readTrap によって通知されていません。ありがとうございました

4

3 に答える 3

0

メソッドがキュー(おそらく新しいステータス?)に送信され、キューから送信さBlockingQueueれるように、共有を検討することもできます。これにより、待機/通知を行うことなく、すべてのロックとシグナリングが処理されます。readTrap(...)add()loginUser(...)take()

コードのデバッグに関してはsyncObject、がprivate finalオブジェクトであることを確認して、同じオブジェクト参照が待機と通知の両方で共有されるようにする必要があります。明らかに、それらが異なるオブジェクトから機能している場合、コードは機能しません。

また、ブロックでステータスを設定する必要があります。synchronizedここで違いが生じるかどうかはわかりませんが、コードにとって重要な値はすべてmutexブロックに含める必要があります。両方の方法でステータスの値を出力して、思ったとおりに更新されていることを確認することを検討してください。

于 2013-02-01T19:19:03.403 に答える
0

この種のことを行う唯一の方法ではありませんが、人々はこの種のフローを解決策と考えるのが一般的です。(これが意味をなさないほど抽象的でないことを願っています。)

--方法1--

  1. 何かの一部をする
  2. 何らかの作業を非同期で行うように別の信号を送る
  3. 結果が出るまで何もしない
  4. 始めたことを終わらせる
  5. 完了ステータスを別のコードに返します。

その方法でも実行できますが、2 つのステップに分割する別の方法よりもはるかに難しいことがよくあります。

--方法2--

パートA

  1. 何かの一部をする
  2. 進行中の作業を保存します
  3. 何らかの作業を非同期で行うように別の信号を送る
  4. 気にしないで

パートB

  1. 他の処理が完了したことを通知します。
  2. 進行中の作業を取得する
  3. 残りの作業を行う
  4. すべて完了

重要な違いの 1 つは、最初の方法で、実際には、このようなものを呼び出すコードに返すことができる結果ステータスがあることです。2 番目の方法では、2 つの部分が同期していないため、それを行うことはできません。

何をしたいのかは、発信者が何を必要としているかによって異なります。

実行する必要がある SNMP コマンドのリストがあるかもしれません。もしそうなら、あなたが必要とするのは、パート Bが完了したときにリストから外したものをマークするか、失敗をマークして、他の誰かが再試行したり、誰かに通知したりできるようにすることだけです。

おそらく、SNMP コマンドには順序があり、順番に 1 つずつ実行する必要があります。最初の方法は、呼び出しを順番に配置できるため、うまく機能します。2 番目の方法では、パート Bの非同期完了がルックアップしてから、シーケンスの次の項目を開始する必要があるため、これが難しくなります。それは複雑になります。

于 2013-02-01T19:32:35.337 に答える
0

syncObject オブジェクトを最終的に作成してください (private Object syncObject = new Object();); 同期ブロックはオブジェクト参照を使用することに注意してください。そのため、オブジェクト参照が変更された場合、必要な動作が表示されません。

また、両方の機能から同期を削除してください。なぜそれが必要なのですか? 両方のスレッドが同じオブジェクトで動作している場合。問題を引き起こす可能性があります。同期されたメソッドは、この参照を同期に使用することに注意してください。

于 2013-02-01T19:39:26.583 に答える