4

invokeLater() Runnable で同期性を確保する必要があるかどうか疑問に思っていました。

デッドロックが発生しており、並行性を維持しながらそれを克服する必要があります。

これは良いコードの例ですか?:

private String text;

private void updateText()
{
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            synchronized(FrameImpl.this)
            {
                someLabel.setText(text);
            }
        }
    });
}

textかなり悪い例で申し訳ありませんが、は別のスレッドによって変更されており、注入できず、正しい値に依存していると想定する必要があります。

これは適切な解決策ですか、それとも、同期されたコードを未知のコンテキストに送信することで、意図せずにデッドロックの問題を引き起こすのでしょうか..?

ありがとう。

4

2 に答える 2

6

より良い解決策は、次のようなものです。

public class Whatever {
    private String text;
    private final Object TEXT_LOCK = new Object();

    public void setText(final String newText) {
        synchronized (TEXT_LOCK) {
            text = newText;
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                someLabel.setText(newText);
            }
        });
    }

    public String getText() {
        synchronized (TEXT_LOCK) {
            return text;
        }
    }
}

これにより、2 つのスレッドがsetText同時に呼び出しを試みた場合に、互いに干渉しないようになります。最初のスレッドは の値を設定し、その値でtextUI 更新をキューに入れます。2 番目のスレッドも値を設定しtext、2 番目の UI 更新をキューに入れます。

最終的に、UI には最終的に最新のテキスト値が表示されますが、内部text変数にはすぐに最新の値が含まれます。

いくつかのメモ:

  1. 別のロック オブジェクト (つまりTEXT_LOCK) を使用すると、別の場所のコードがインスタンスのモニターをロックし、Whatever不注意でデッドロックを引き起こす可能性がなくなります。ロック オブジェクトを常に厳密に制御することをお勧めします。また、同期ブロックのサイズを最小限に抑えることをお勧めします。
  2. 上記のようにデッドロックに対して脆弱になる可能性があるという警告を条件として、メソッド全体を同期させることができます。setText
  3. 不変であっても、値の読み取りtextも同期する必要があります。StringsJava メモリ モデルには微妙な点があり、複数のスレッドで読み書きできる変数を常に同期する必要があります。

Brian Goetz のJava Concurrency in Practiceを参照して、同時実行のトリッキーな部分 (メモリ モデルの奇妙さを含む) を深く掘り下げてください。

于 2011-07-27T04:46:35.847 に答える
-2

これで問題ありません。タスクからのすべての出力を InvokeLater() にラップする必要があります。BackGround タスクから GUI を更新する別の例はこちらです。

private String text;

private void updateText() {

    synchronized (FrameImpl.this) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                someLabel.setText(text);
            }
        });
    }
}
于 2011-07-27T04:28:12.433 に答える