- - PR -
コマンド終了待ち時のタイムアウト処理
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-09-29 11:43
javaからコマンドを発行してコマンド終了を待つ処理において、タイムアウトの設定ができないかを検討していまして、以下のように監視スレッドを生成する方法を考えました。
(監視スレッドでタイムアウト時間分sleepして、sleepが終わると、コマンド発行側にinterruptをかけます) −−−−−−−−−コマンド発行側−−−−−−−−−−−−− Thread kansi = new Kansi( Thread.currentThread() ); kansi.start(); String cmdExtract[] = {"xxxx", "yyy"}; Process process= Runtime.getRuntime().exec(cmdExtract); try { int code = process.waitFor(); kansi.interrupt(); } catch(InterruptedException e) { System.out.println("timeout"); } −−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−監視スレッド−−−−−−−−−−−−−− class Kansi extends Thread { private Thread parent; public Kansi(Thread parent) { this.parent = parent; } public void run() { try { Thread.sleep(timeoutLimit); parent.interrupt(); } catch(InterruptedException e) { } } } −−−−−−−−−−−−−−−−−−−−−−−−−−−−− この方法でほぼ問題は無いと考えておりますが、「監視スレッドからのinterruptが、コマンド発行側のtry,catchの後で効く事が無いか」ちょっと気になっています。 もしそのケースがあるとなると、コマンド発行側において、コマンド処理が終わった後、予期しない所でinterruptが効いてしまう事になります。 このあたりについて、情報をお持ちの方がいらっしゃいましたら、ご指導お願いいたします。 なお、JDKは5.0です。 | ||||||||
|
投稿日時: 2006-10-01 18:39
「コマンド発行側」も
「専用の」スレッドを使うのはどうでしょう。
[ メッセージ編集済み 編集者: squeak 編集日時 2006-10-01 20:09 ] | ||||||||
|
投稿日時: 2006-10-02 17:53
返信ありがとうございます。
確かに専用スレッドを作る事で、「予期しない所でinterrutが効いてしまう」危険性は、避けられるように思います。 逆に言うと、最初のコーディングでは、その危険性は避けられないという事でしょうか? もしそのあたりについて、ご存知の方がいらっしゃれば、指摘頂ければ幸いです。 | ||||||||
|
投稿日時: 2006-10-02 18:38
可能だとは思いますよ。面倒でも良ければ、 スレッド間で二つのオブジェクトのwait()/notify()を駆使して。
これならタイムアウト監視スレッドからのinterrupt()の発生が 「起動イベント.wait()」と「プロセスを起動して待機」の どちらかの待機状態でのみ発生する事を保証できます。 #あまり細かく検証していないのでツッコミ歓迎…。 他には、java.util.concurrent.CyclicBarrierなどのクラスで可能かもしれないし、 java.util.concurrent.ExecutorServiceにプロセス起動をsubmit()して、 Futureをタイムアウト付きで待機する方法がスマートかもしれません。 | ||||||||
|
投稿日時: 2006-10-02 21:54
以下のようなコードはいかがでしょう。
厳密な検証はしていませんが。
スレッドはあまり得意ではないので、ツッコミがあればよろしくです。 | ||||||||
|
投稿日時: 2006-10-02 23:07
ソースをレビューした観想としてはあしゅさんのコードが安全そう。
かつのりのコードはisAlive()〜interrupt()の間に "ANY TASK"部分を抜けるケースがありそうな気がするなぁ。 try-catchブロック以後になんにもコードがなければ まずは発生しないとは思うのですが。 そこだけ同期すれば確実なのかな。 だとしてもこの方式が比較的すっきりまとまりそうな気もするなぁ。 | ||||||||
|
投稿日時: 2006-10-03 10:49
確かに。プロセス起動側を別スレッドにすれば簡単ですね。
この書き込みを見てそのまま回答したので、 プロセス起動を既存のスレッドで実装する方法しか考えなかったです。
起動したプロセスの完了が寿命なスレッドなら割り込んでも安全なのでは? 終了したスレッドにinterrupt()するのなら実害なさそうに思うので。 Javadocには記述を見つけられなかったので確証はないですけど。 | ||||||||
|
投稿日時: 2006-10-03 14:40
様々な案を返信ありがとうございます。
確かに、かつのりさんの案のように、プロセス起動側を別スレッドにする方法は、全く考えつきませんでした。 ただ、start() メソッドは、synchronizedが必要無いように思うのですが、如何でしょうか? それから、あしゅさんが言われるように、私が実験した所では、終了したスレッドにinterrupt()しても実害は無いようでした。 なお、あしゅさんが「2006-10-02 18:38」に投稿された方法は、デッドロックになるのではないでしょうか? (プロセス起動スレッドが「起動イベント」を確保している間に、タイムアウト監視スレッドからのnotifyを待つ。 タイムアウト監視スレッドは、notify発行の前に、「起動イベント」を確保できない。) いずれにしろ、プロセス起動側を別スレッドにするやり方が、比較的シンプルで安全な方法のように思われました。 いろいろ、ありがとうございました。 |