0

whileループがロックを無期限に盗むため、次のコードが機能しないことがわかりました。

public void run()
{
    while(true)
    {
        synchronized(run)
        {
            if (!run) break;
            [code]
        }
    }
}

public void stopRunning()
{
    synchronized(run)
    {
        run = false;
    }
}

私の目標は、run()関数が実際に実行されていないことがわかるまで、stopRunning()コマンドから戻らないようにすることです。run関数が、破棄中の他のものを参照し続けるのを防ごうとしています。私が最初に考えたのは、同期(実行)の前にThread.sleep(100)などのコード行を追加して、ロックが確実に解除されるようにすることです。これは推奨される方法ですか、それとも[愚かな/明白な]何かを見落としていますか?

ありがとう!

4

5 に答える 5

2

run() が処理を終了するまで stopRunning() をブロックする必要がある場合は、1 に設定された CountDownLatch を使用するだけです。 . stopRunning では、run() を終了する条件を設定してから、stoppedSignal.await() を呼び出すことができます。run() がカウントダウンしてラッチを「解放」するまで、処理は続行されません。これは、少しすっきりした方法の 1 つにすぎません。削除されたすべての同期ブロックのもの。

「同期」キーワードに注意してください。これは非常に鈍くて古いツールです。同時実行パッケージには、特定の目的をよりきちんと満たす素晴らしい機能がいくつかあります。「Concurrency In Practice」は、それに関する素晴らしい本です。

于 2012-10-04T00:05:02.167 に答える
0

runをsynchronized(run)ロックしますが、run.wait()run()が実行されているスレッドをフリーズするために使用できます。別のスレッドでは、run.notify()またはを使用run.notifyAll()してrun()を続行します。

同期は、スレッド間で同期するために使用されます。2つ以上の間に潜在的な競合状態がある場合にのみ使用してください。

于 2012-10-04T00:12:50.050 に答える
0

このようなもので十分でしょうか?

public void run()
{
    while(run)
    {
        [code]
    }

   onRunStopped();
}

public void stopRunning()
{
    run = false;
}

public void onRunStopped()
{
    // Cleanup
}
于 2012-10-04T00:04:56.873 に答える
0

おそらくもっと洗練された解決策がありますが、次の変更で解決できると思います。

private boolean lock;

public void run() 
{ 
    while(true) 
    { 
        synchronized(lock) 
        { 
            if (!run) break; 
            [code] 
        } 
    } 
} 

public void stopRunning() 
{ 
    run = false; 
    synchronized(lock){ } 
} 
于 2012-10-04T01:37:55.120 に答える
0

「実行」オブジェクトがコードの両方のポイントから同じであることを確認してください。

while ループは、stopRunning() メソッドと同じオブジェクトに同期する必要があります。

while ループがロックを独占しているのではなく、2 つのコードが別のオブジェクトを参照している可能性が高くなります。しかし、実行オブジェクトがコードに表示されていないため、わかりません。

于 2012-10-04T00:33:07.517 に答える