2016-03-22 7 views
1

私は、私の会社のアプリケーションの一部として集中的な操作を書いてUIスレッドから離しておく必要があります。非常にスレッドで安全でないコンポーネントがたくさんあります。楽しい時間。Java:値を内部クラスに渡すスレッドの安全性

私は自分でこれを単純化しようとしています。それで、どうすればいいのでしょうか。

1)スレッドで安全でないコンポーネントからのデータは、読み書きされず、書き込まれません。以下に示すように

2)そのデータへの参照は、バックグラウンドスレッドに渡されるであろう:

final Object someData = getSomeData(); 
     Runnable task = new Runnable() { 
      @Override 
      public void run() { 
       doSomething(someData); 
      } 
     }; 

はまた、モーダルダイアログが誤ってこのプロセスの間のいずれかの値を変更することからユーザーをブロックします。したがって、someDataの状態はプロセス全体で変更されず、ただ読み込まれます。

私はいつもメモリの一貫性の問題について非常に編集的です。ここには何かありますか?このように参照を渡すことで、バックグラウンドスレッドはその時点で最新の状態になりますか?

ありがとうございました。

+0

これが意味することは、リファレンスが古くならないということです。あなたがそれを使って作業するたびに、現在の状態が反映されます。 – ChiefTwoPencils

+0

スレッドに渡す前にsomeDataをクローンします。スレッドがそのデータで何かをやり終えたら、その結果をUIに戻すことができます。 – Heri

+0

内部クラスは実際にはそれと関係がありません。この問題は2番目のスレッドであり、通常のスレッドセーフティの注意事項、 'synchronized'または' volatile'が必要です。 – EJP

答えて

2

Runnableを使用して新しいスレッドを開始する場合、またはExecutorにそれを送信する場合、新しいスレッドはスレッドの作成までに発生したすべてのアクションを表示します。したがって、バックグラウンドスレッドの実行中に状態が変わらない限り、データは表示されます。これは、不変オブジェクトで保証するのが容易になります。

Executor

メモリー整合性効果:前キュータにRunnableオブジェクトを提出するスレッド内のアクションが起こる前に、その実行は、おそらく別のスレッドでは、開始されます。

Thread.start

文がThread.start、その文で事前発生関係はまた、新しいスレッドで実行されるすべての文との事前発生関係を持っているすべてのステートメントを呼び出します。新しいスレッドの作成につながったコードの効果は、新しいスレッドに見えます。

UIスレッドにデータを送信する場合は、変更がinvokeLaterを通過するかどうかを確認する必要があります。 Is happens-before relation given in case of invokeLater() or invokeAndWait?

Swing Workerを使用すると、このうちのいくつかが管理されます。これにより、バックグラウンドスレッドで実行するメソッドをオーバーライドすることができ、終了したイベントディスパッチスレッドで別のスレッドを実行することができます。

+0

ありがとうございます。これはまさに私が探していた答えです。モーダルダイアログ(それらを閉じる機能を無効にする)を使用することで、このプロセス中にアプリケーションの状態に変更が加えられるのを防ぐことができます。それは最もエレガントな解決策ではありませんが、私の会社が完全なコードを書き直すまでは、私が持っている最良の選択です。 – user2223059

関連する問題