1

次のJavaメソッドがスレッドセーフかどうかを判断しようとしています。

public Object calledByMultipleThreads() {
    final Object[] item = new Object[1];

    if (!EventQueue.isDispatchThread()) {
        try {
            EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    helperMethod(item)
                }
            });
        } catch (InterruptedException | InvocationTargetException ex) {
            // logging...
        }
    } else {
        helperMethod(item)

    }

    return item[0];
}

private void helperMethod(Object[] item) {
    item[0] = new Object();
}

私はそれfinal Object[] item = new Object[1]が回避策であることを知っています(のようなものfinal Object itemは内部で変更できなかったのでRunnable)。invokeAndWaitが使用されているため、は、item[0]によって参照される前に設定されますreturnが、呼び出し元のスレッド(EDTではない)がitem配列の更新を認識せず、を返す可能性があるのではないかと心配していnullます。これは可能ですか?安全性をテストする方法はありますか?

4

2 に答える 2

1

実装方法の詳細により、次の呼び出し元に制御が戻る前にinvokeAndWait、発生内で発生するすべてのアクションが発生します。Runnable invokeAndWait

1233  同期(ロック){ 
1234 ツールキット。getEventQueue()。postEvent(イベント);
1235 while(!event。isDispatched()){
1236 ロック。待つ();
1237 }
1238 }

言い換えれば、あなたがしていることは安全です。一方、テストによってそのような保証を保証する方法はありません:)

于 2013-02-20T18:20:31.397 に答える
1

final配列は、インスタンス以外のフィールドよりも自動的にスレッドセーフではありません。

ただし、ここではスレッドセーフの問題はありません。内の割り当てとそのメソッドが戻るまでの間に発生が発生します。EventQueueinvokeAndWait

invokeAndWaitは(効果的な)デッドロックを引き起こす可能性があります。EventQueue.invokeLater非EDTスレッドにポストバックするには、同様の方法を使用することをお勧めします。

于 2013-02-20T18:20:34.860 に答える