4

私のソフトウェアを説明しましょう。私のソフトウェアが単純に行うことは、10 個のスレッドを作成し、各スレッドに多数のタスクを割り当てることです。次に、各スレッドは、cmd バッチ ファイルを開始するランタイム プロセスを作成します。このプロセスは、デバイス (約 200 個あります) に telnet 接続して構成をポーリングするプログラムを開始します。私のプロセス作成のコードは次のとおりです。

Process p1 = java.lang.Runtime.getRuntime().exec("cmd /c  start /b /wait " + batchFile); 
int returnVal = p1.waitFor();

batchFileバッチ ファイルのフル パスです。誤解しないでください。ソフトウェアは実行の 100% まで正常に動作し、約 95% で 1 回だけハングしたので、その解決策を見つけようとしています。なぜハングアップしたかは今の問題ではなく、後でハングアップに対処する方法..!

ここでの問題は、プロセスが完了するのを待つ必要があることです。これは、telnet クライアントがファイルに書き込み、後でスレッドで読み取るためです。したがって、の使用.waitFor()。私の質問は、外部プログラムがハングしたことをスレッドに理解させるにはどうすればよいですか? 言い換えれば、外部プログラムに終了までの時間制限を与えることはできますか? そうでない場合、スレッドはプロセスを強制終了しますか?

また、エラーと出力ストリームの読み取りについて読みました。しかし、ここでは当てはまらないと思いますか?

4

1 に答える 1

3

また、エラーと出力ストリームの読み取りについて読みました。しかし、ここでは当てはまらないと思いますか?

ほぼ間違いなく、適用可能です。ProcessBuilderの代わりに を使用してみてRuntime.exec、 を呼び出す前にすべての出力を読んでくださいwaitFor。例 (例外処理が省略されています。特に、プロセスが実際に終了する前にwaitForスローされる可能性があります)InterruptedException

    ProcessBuilder pb = new ProcessBuilder(
        "cmd", "/c", "start", "/b", "/wait", batchFile);
    pb.redirectErrorStream(true);
    Process p = pb.start();
    IOUtils.closeQuietly(p.getOutputStream());
    IOUtils.copy(p.getInputStream(), System.out);
    // or alternatively throw away the output using
    // IOUtils.copy(p.getInputStream(), NullOutputStream.NULL_OUTPUT_STREAM);
    IOUtils.closeQuietly(p.getInputStream());
    int returnVal = p.waitFor();

(IOUtils と NullOutputStream はApache commons-ioからのものです)。

タイトルの実際の質問に答えるには、出力を適切に読み取った後でもプロセスがハングする場合は、 を使用p.destroy()してプロセスを強制終了する必要がある場合があります。次のようなタイマータスクを定義できます

    public class TimeoutProcessKiller extends TimerTask {
      private Process p;
      public TimeoutProcessKiller(Process p) {
        this.p = p;
      }

      public void run() {
        p.destroy();
      }
    }

そして、する

    // single shared timer instance
    Timer t = new Timer();

    // for each device
    Process p = pb.start();
    TimerTask killer = new TimeoutProcessKiller(p);
    t.schedule(killer, 30000);
    // ... read output stream as before ...
    int returnVal = p.waitFor();
    killer.cancel();

これにより、プロセスが 30 秒以上実行されている場合にプロセスが強制終了されます (schedule呼び出しを調整してタイムアウトを変更します)。

于 2013-01-23T15:56:32.947 に答える