2011-07-25 6 views
2

addShutdownHook()を使用してCtrl + Cを処理するSwingアプリケーションがあります。通常の状況でJLabelテキストを変更する関数それがぶら下がります。JVMがシャットダウンしていることの検出

私は、スイングEDTが終了したか何かを待っているという問題があると想定します。

EDTが終了したか、または「完了」している(Swingメソッドの呼び出しを避けることができる)か、Ctrl-Cで通常のウィンドウを閉じるような動作を防ぐ方法がありますか? ?

を私はstop()と呼ばれるクラスのメソッドを持っている:だけ明確にする


。通常の状況下では、これは(補足start()とともに)呼び出され、stop()が発生したという視覚的なフィードバックのために、JLabelを更新する原因となるカスケードをトリガーします。

私のシャットダウンフックが実行されるとき、いくつかのリソースを正常にシャットダウンするには、stop()に電話する必要があります。

私はSwing EDTがないことを検出することができるので、stop()を書き換えて、Swingの不足を検出し、Swing機能への呼び出しを回避できるようにします。

答えて

0

へのコールによるアプリケーションのシャットダウンシャットダウンフックの先頭にフラグを設定し、これを(前もって設定したオブジェクトを介して)私のstop()メソッドを使用して、このフラグをテストしてSwingメソッドを呼び出すかどうかを決定することができます。

シャットダウンフラグが設定されていないと、Swingメソッドが呼び出されます。 t。

private static final Thread DUMMY_HOOK = new Thread(); 

public static boolean isShuttingDown() 
{ 
    try { 
     Runtime.getRuntime().addShutdownHook(DUMMY_HOOK); 
     Runtime.getRuntime().removeShutdownHook(DUMMY_HOOK); 
    } catch (IllegalStateException e) { 
     return true; 
    } 

    return false; 
} 

しかし、可能な並行性の問題を忘れないでください:

+0

これは時間のいくつかの動作します。しかし、それはまだ物事が停止される順序に依存しています。スレッドがシャットダウンする順序やシャットダウンフックが開始される順序を制御することはできないため、ロックアップの原因となったイベントの順序は引き続き発生します。(1)Ctrl + CによりJVMがシャットダウンを開始します。 Swingスレッドが閉じられ、あなたのシャットダウンフックがまだ呼び出されていない、(3)JLabelが変更を要求する呼び出しが呼び出された、アプリケーションがハングアップする、(4)シャットダウンフックが呼び出される、無効/ロックアップコールを防止します。 – jefflunt

+0

@normalocity:少なくともこの問題の文脈では、それを心配しないでください。あなたが記述しているようなシーケンス(2)、(3)が発生した場合、それは対処する必要がある別の問題です。シャットダウンフックを使用していなくても発生します。 –

+0

まあ、あなたのコードがうまくいけばうれしいです。あなたは結局、あなた自身のコードのエンジニアなので、心配しなければ、心配する必要はありません。私はあなたの他の質問を思い出させます:http://stackoverflow.com/questions/508850/java-concurrency-cynicism-gone-too-far私は本当に並行コードが大好きなので、私はこれらのマルチスレッドの質問に取り組んでいるファンです、 すべてであります。 – jefflunt

2

シャットダウンフックは、アプリケーションのシャットダウンが要求されているため、他のサービスが既知の状態(たとえば、UIイベント処理スレッドなど)になることを期待すべきではありません。フックの制御内で100%でないものを更新しようとするシャットダウンフックを書き込むと、これやその他の動作が発生し、トラブルシューティングが困難になります。

addShutdownHookの方法では、具体的にこのケースについて言及しています。このような操作を行うと、予期しない結果が発生する可能性があるため注意してください。 the documentationから

シャットダウンフックは仮想 マシンのライフサイクルの微妙な時期に起動、したがって、防御的にコード化されなければなりません。特に、 ではスレッドセーフで、デッドロックをできるだけ避けるために書かれていなければなりません また、自分自身のシャットダウンフックを登録した可能性のあるサービス に盲目的に依存してはならないため、シャットダウン中に 自身がシャットダウンする可能性があります。この場合

スイングは、あなたがコントロールしていないマルチスレッドのUIシステムであることから、私はあなたしているプログラムの人生のシャットダウン段階でUIには何も変更しようとしていないことをお勧めします。そうすることで、スレッドがどのようにシャットダウンするようにスケジューリングされるかに応じて、奇妙で、予測できない、時には反復不能な状況が実行ごとに異なり、あるマシンから次のマシンに変化することになります。どのように、そしていつ、別のスレッドがその作業を停止するかは、線形で予測可能な方法で行われるようには設計されていません。そのため、特定の状態にある別のスレッドが特定の時刻に依存しているマルチスレッドプログラムで記述したコードは、(これらのスレッドがそれぞれの状態について明確に通信している場合を除いて)、問題。

私は、「なぜシャットダウンプロセス中にJLabelを変更したいのですか?"シャットダウンする前に何かの状態を変更したい場合は、の方が良い場合はキーボード入力を通常のイベントとしてキャッチし(アプリケーションを終了させないようにする)、JLabelのテキストを変更してからSystem.runFinalization()および/またはSystem.ext(int)

+0

これは私が「EDTが終了した、または完了したと判断する方法があるか」という理由で、Swingの関数を呼び出すことを避けることができます。 –

+0

実際はそうではありません。要点は、シャットダウンプロセスでは、別のスレッドの状態に頼ることができないということです。そうすることは、常に困難な道を導くことになります。私は別のパラグラフで答えを更新し、代替案を提示しました。 – jefflunt

+0

ありがとうございます。私はJLabelを変更したくありません - 私は通常の状況下で使用する関数を呼び出しています。 –

2

次のハックは、JVMが周りの任意のフラグを渡さずにシャットダウンを実行中であるかどうかを判断するのに役立ちます。

関連する問題