2011-08-03 12 views
2

私が使用したJFrameを開始非GUIのスレッドを持っているJavaスレッドはinvokeLater()とどのように同期しますか?

java.awt.EventQueue.invokeLater(new Runnable() { 

    public void run() { 
     cardReadPunchGUI = new IBM1622GUI(); // instantiate 
     cardReadPunchGUI.setVisible(true); 
    } 
}); 

IBM1622GUIのコンストラクタの一部は私の非GUIスレッドがへのアクセスを必要とする自分自身のための「モデル」、インスタンス化:

cardReadPunch = IBM1622GUI.getModel(); 

を私の非GUIスレッドが "後で呼び出された"新しいGUIと同期する正しい方法は何ですか? (同期がなければ、もちろん、IBM1622GUI.getModel()はちょうどnullを返す傾向がある。)

javax.swing.SwingUtilities.invokeAndWait(Runnable doRun); 

代わり

+0

Javadocのすぐ下にあります。 [invokeAndWait](http://download.oracle.com/javase/6/docs/api/java/awt/EventQueue.html#invokeAndWait(java.lang.Runnable)) – Bringer128

答えて

4

使用。

AWTイベント ディスパッチスレッドでdoRun.run()が同期して実行されます。この呼び出しは、保留中のすべてのAWTイベントが処理され、doRun.run()が返されるまでブロックされます( )。

+0

これは実際には本当に悪いことです。 invokeAndWait()は決して使用しないでください。あなたのプログラム全体をロックすることができます。 invokeLater()を使用します。実際にinvokeAndWait()を使用すべき実際の事例は実際にはありません。彼らが私がここで言っているのと同じことを言う文書を読んでください。避けてください。 – chubbsondubs

+2

@chubbard:これは非常に文脈に敏感なことです。もしそれが非ブロッキング操作であれば、 'invokeAndWait()'はバックグラウンドスレッドから呼び出されているときに特に安全に呼び出すことができます。バックグラウンドスレッドから呼び出されている場合は、文字通り「プログラム全体をロックする」ことはできません。 –

+0

@chubbard:Javadocが警告するのは、このメソッドをEDTから呼び出すことです。 OPは特に、GUI以外のスレッドから呼び出していると述べています。 – cgull

1

通常、スレッドにパラメータを渡します。ロジックをバックグラウンドで実行します。 SwingUtilities.invokeLater()を使用して、必要な変更をUIスレッドのこれらのオブジェクトまたはUI要素のいずれかにポストバックします。通常、私はバックグラウンドスレッド上で実行すべきものと、UIスレッド上で実行すべきものを指定できるシンプルなユーティリティを作成します。 SwingWorkerはあなたが使うことができるものですが、使用するのは非常に苦労します。次のような単純なもの:

new AsyncThread<Param,T>() { 
    public T executeInBackground(Param param) { 
     // do something long running 
     T result = // do something long running; 
     return T; 
    } 

    public void executeOnUI(T result) { 
     // update the UI here, or modify the model, etc. 
    } 
}.execute(param); 

AsyncThreadは別のスレッドでexecuteInBackground()メソッドを実行します。その後、内部的にSwingUtilities.invokeLater()を使用してUIスレッドにポストバックします。次に、executeOnUIはUIスレッドで実行されます。 execute()メソッドは、バックグラウンドで実行するスレッド、例外を処理するスレッドなどを作成することができます。

GUIをスレッドから開始し、GUIでモデルや必要な部分を渡すようにしますスレッド。逆の代わりに。そうすれば、実行中のバックグラウンドスレッドに関するフィードバックをUIに与えることができます。しかし、UIスレッドが同時に読み書きするモデルのメンバーにバックグラウンドスレッドが触れる(書き込み/変更/変更)ことはできません。したがって、バックグラウンドスレッドに応答してモデルを変更する予定がある場合は、UIスレッドにポストバックして安全にしてください。

+2

1. SwingWorkerを使用するのが苦痛である理由が分かりませんが、同じことをするユーティリティを作成するためにあなたが行ったように見えますが、維持する。 2. ** UI **スレッドが行ったことの結果を必要とする**バックグラウンド**スレッドであるという点が欠落しています。 –

+0

それを使用しないことは私の好みです。それの初期はかなりひどいものでした。インターフェースは多少変更されていますが、例外を自動的に処理して自動的にフィードバックを与えてスピナーダイアログを表示するのが好きなので、新しいバックグラウンドジョブを作成するのはかなり簡単です。私はバックグラウンドジョブを簡単にやってくれるきついクラスを作ることができることを発見しました。 SwingWorkerにはもっと多くのコードが必要ですが、必要に応じて使用してください。 – chubbsondubs

2

Idでは、GUI以外のスレッドとGUIスレッドの両方で1に初期化されたCountDownLatchを共有することをお勧めします。

起動時の非GUIスレッドは、ブロックされた状態になるlatch.await()を呼び出します。

初期化が終了すると、GUIスレッドはlatch.countDown()を呼び出し、非GUIスレッドが待機呼び出しから終了し、両方のスレッドが同期します。

+0

これはクールです。私はそれを聞いていないだろう。 – Chap

2

あなたがアクセス権を持っている場合は、その特定のロジックをいつでもSwingスレッドの外に、invokeLaterというスレッドに移動できます。 IBM622GUIのコンストラクタが正常に動作していると仮定すると、Swingスレッドの中で何をしているのかについては安全ではありません。

これ以外にも、さまざまなメカニズムを利用できます。

  1. invokeAndWaitを使用すると、cgullが私を殴って言ってしまいます。
  2. 実行可能ファイルに直接参照の代わりにFutureの値を設定し、将来のgetメソッドを呼び出すことによってメインスレッドをブロックすることができます。
  3. 開始カウントが1のメインスレッドの場合はCountDownLatch、スイングスレッドの場合はcountDown()になります。

同期に役立つ多くのユーティリティがあります。

+0

**同期に役立つ多くのユーティリティがあります。**はい、確かにあります。私がこれまで以上に卓越しているJavaデザイナーのおかげで、Javaの並行性ツールがちょっとしたものではないかと思います。 – Chap

関連する問題