ServletContextLisntener#contextDestroyedついて
下記の様なコードがあったとします。
Tomcat上で動くServletContextListenerImpl#contextDestroyed内の処理にて
ポイント1とポイント2を確実に通過するには
どのような設定orコーディングが必要ですか?
※宿題ではありません。月曜に製造完です。(..);
class ThreadManager {
private static final ThreadManager manager = new ThreadManager();
private final Thread t;
private boolean isStop;
pulbic ThreadManger () {
isStop = false;
final Thread t = new Thread () {
public void run () {
for ( ; ! this.isStop ; ) {
Thread.sleep(300000);
}
}
//ポイント1
}
t.start();
this.t = t;
}
public static ThreadManager getInstance () {
return manager;
}
public void stop () {
this.isStop = true;
}
public void isAlive () {
return this.isAlive();
}
}
public class ServletContextListenerImpl implements ServletContextListener {
public void contextInitialzed () {}
public void contextDestroyed () {
final ThreadManager manager = ThreadManager.getInstance();
manager.stop();
while (manager.isAlive()) {
//Thread.sleep(2000)する
}
//ポイント2
}
}
No.2ベストアンサー
- 回答日時:
> ServletContextListenerImpl#contextInitialzed
> がコールされ数十秒でスレッドが強制終了されて
> ServletContextListenerImpl#contextDestroyed
> のポイント2を通過できません
contextInitialzed は起動時、contextDestroyed は終了時に呼ばれるはずですが、
・Eclipse を使って Tomcat を起動した場合には両方とも正常に呼ばれる
・Tomcat 単独で動かした場合には終了時に contextDestroyed が呼ばれていない
という事ででしょうか?
これらをどうやって確認したのでしょう?
catalina.out などのへの出力を見たのでしょうか?
基本的にはTomcatの起動の仕方によって変わることは無いと思います。
ただし、JVMが強制終了させた場合などは contextDestroyed が呼ばれないことはありえます。例えば、linuxで kill -KILL によってTomcatの実行JVMを終了させた場合は呼ばれないと思われます。
> 基本的にinterruptするのではなく、
> 質問で言えばsleep中(処理中)とし
> 処理を終えたら次の処理はせず安全に停止する
interrupt を使ってもこのような動作はできます。
というか、このような動作をさせるのが interrupt の最も一般的な使い方だと思います。
sleep や wait の最中であれば、InterruptedException が発生しますが、それ以外であれば、Thread.isInterrupted() でtrueが帰るようになるだけです。
例) ------------------------------------------
public void run () {
while (!Thread.currentThread().isInterrupted()) {
// ・
// ・
// ・
try {
Thread.sleep(300000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();// 割り込みフラグを立て直す
// sleep 中に interrupt された場合の処理
}
}
}
----------------------------------------------
http://www.ibm.com/developerworks/jp/java/librar …
No.1
- 回答日時:
細かいスペルミスやセミコロンや例外処理の記述漏れなどを修正したとしても、このコードはコンパイルエラーになるのでは?
さらには根本的にスレッドセーフになっていません。
以下、スペルミスなど以外の問題点を書きます。
1. ポイント1の場所
ポイント1はどのメソッドにも含まれていないので、どうやっても通過しません。
強いて言えば、ポイント1にフィールド定義などを書いた場合はオブジェクトが生成されたタイミングで実行されることにはなります。
2. isStop
無名クラス内で isStop を参照していますが、this は無名クラス自身のオブジェクトを指してしまいますので、単に isStop とするか ThreadManager.this.isStop としなければいけません。
また、isStop を複数のスレッドから参照・変更しようとしているようですが、同期化もされおらず volatile でもないフィールドは正しい値が見えない可能性が有ります。
キャンセルには interrupt を使うのが定石です。
http://www.itarchitect.jp/technology_and_program …
interrupt を使うのが難しければ、Thread を無名クラスではなく名前を持った内部クラスとして定義し、その中に isStop を持たせて、同期化か volatile にすれば一応スレッドセーフにはなると思います。isStop が false になっても sleep が終わるまではチェックされませんし、お勧めはしませんが。
3. isAlive()
> public void isAlive() {
> return this.isAlive();
> }
void 型のメソッドで自分自身の呼出し結果を返そうとしても出来ないですよね。
また、
> while (manager.isAlive()) { ・・・
も void 型のメソッドではコンパイルエラーになりますよね。
ただし、戻り値を boolean に変えても、無限再帰に陥るだけですが・・・。
下記のようなコードにするつもりで書き間違えたのかも知れませんが、これでもスレッドセーフの問題は残りますし、isStop が false になっていても、スレッドはまだ sleep 中かも知れません。
public boolean isAlive() {
return !this.isStop; // ※ これもスレッドセーフではない!
}
4. ServletContextListenerImpl の各メソッドのシグネチャー
ServletContextListenerImpl の各メソッドは ServletContextListener のメソッドを実装しようとしているのだと思いますが、引数が違います。
http://mergedoc.sourceforge.jp/tomcat-servletapi …
両方とも ServletContextEvent を引数に取らないと、オーバライドした事になりません。
以上の他にも、スペルミスなどはいろいろ有るようですので修正が必要です。
ポイント2を通す方法、というよりこれらプログラムを動かす方法ですが、 web.xml でこのリスナーに登録すればよいかと。
http://www.techscore.com/tech/J2EE/Servlet/7.html
ただし、他のどこかで ThreadManager をロードするようにしていなければ、ThreadManager で定義したスレッドは、Webアプリケーションがシャットダウンするときに始まってすぐにストップされることになるでしょう。
また、isAlive の実装次第では manager の stop 待ちのループを while ではなく、for を使って回数制限したほうが良いかもしれません。
for (int i = 0; i < 10 && manager.isAlive(); i++) {
//Thread.sleep(2000)する
}
このようなスレッドの終了待ち処理も、出来れば Thread.join(long) を使うような形に持っていった方が良いとは思いますが。
ちなみにJavaのスレッドプログラミングについては下記の書籍が参考になると思います。
http://www.amazon.co.jp/dp/4797337206
参考URL:http://www.ibm.com/developerworks/jp/java/librar …
この回答への補足
遅くなり申し訳ありません。
記述ミスや抜けなど読み取っていただき
しかも的確なアドバイスをいただきありがとうございます。
もう1点質問させてください。
(再度コードを載せると長くなってしまうので
このまま初回の質問のコードをベースに質問させていただきます。
すみません。)
ServletContextListenerImpl#contextInitialzed
(引数抜け)
がサーバー(tomcat)停止時にコールされ
managerが停止するまで待って
安全にスレッド停止したいというコードなのですが、
manager.stop後managerが終了するまで
数分かかる場合についての安全停止についてです。
(基本的にinterruptするのではなく、
質問で言えばsleep中(処理中)とし
処理を終えたら次の処理はせず安全に停止する)
eclipseから起動したtomcatを
eclipseから停止した場合
managerが停止するまで数分掛かろうが
ServletContextListenerImpl#contextDestroyed
のポイント2を通過できます。
しかし、
warでデプロイしたアプリを
サービス登録したtomcatで稼動させ
サービスを停止した場合
ServletContextListenerImpl#contextInitialzed
がコールされ数十秒でスレッドが強制終了されて
ServletContextListenerImpl#contextDestroyed
のポイント2を通過できません
この場合もポイント2を通過する方法?設定?はありませんか?
質問の仕方もへたくそで申し訳ありませんが、
宜しくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Java java final 1 2022/06/10 22:49
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- C言語・C++・C# Windows Formアプリからコンソールを呼び出して文字を出力させたい 8 2023/05/09 10:53
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- Java eclipse実行ができない 2 2022/07/27 04:47
- Java 直し方について教えて頂きたいです。 4 2022/08/13 02:11
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
tryの終了
-
onBlurとonFocusの処理順序につ...
-
doGetとdoPostの違い
-
Javaプログラムからポップアッ...
-
Delphiのマルチスレッドの割り...
-
Tomcat高負荷時の設定について
-
JavaScriptからJAVAクラスを呼...
-
JAVAにおける画像のJPEG保存の...
-
ExcelVBA で文字列の特定の文字...
-
jQueryでString
-
データ未入力時のエラー処理が...
-
アコーディオンメニューをアン...
-
ラジオボタンの選択判定
-
Javaでのデバッグコード削除
-
エクセルVBAで、条件に一致する...
-
「タイプ初期化子が例外をスロ...
-
変数名の付け方
-
レコード件数の表示
-
C#において、同じインスタンス...
-
private static という変数の修飾
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
tryの終了
-
数値の定数を付ける時
-
Javaでのデバッグコード削除
-
C#で別スレッドの終了を知りたい
-
[Java] while(true)の意味
-
Tomcatのスレッドを破棄する方法
-
Javaプログラムからポップアッ...
-
ラジオボタンの選択判定
-
JavaScriptからJAVAクラスを呼...
-
WPF C#でF10のイベント取得方法...
-
PHPでDB処理中にプログレスバー...
-
素数判定を再帰処理で
-
Javaアプリケーション実行の返...
-
switch文の中に、throws new Ex...
-
doGetとdoPostの違い
-
JDBCでテーブルUPDATE後の再検...
-
Tomcat高負荷時の設定について
-
ラベルの表示までが異常に遅い...
-
ExcelVBA で文字列の特定の文字...
-
SwingUtilities.invokeLater(ne...
おすすめ情報