4

私は2つのプロセスjava:processAとprocessB(2つのスレッドではなく2つのプロセスjava.exe)を持つプログラムを持っています。プロセスAから以下のコードブロックを使用してプロセスBを呼び出しますこのコードは以下のRunTaskクラスにラップされています

public class RunTask implements Callable<Object> {

private String runParams;

public String getRunParams() {
    return runParams;
}

public void setRunParams(String runParams) {
    this.runParams = runParams;
}

@Override
public Object call() throws Exception {
    try {
        //System.out.println("run:" + runParams);
        Process procB = Runtime.getRuntime().exec("java -jar processB.jar);
        DataInputStream ls_in = new DataInputStream(procB.getInputStream());
        String ls_str;
        while ((ls_str = ls_in.readLine()) != null) {
            System.out.println(ls_str);
        }

    } catch (Exception exp) {
        exp.printStackTrace();
    }
    return null;
}
}

およびメインクラス私はexecutorを使用します

   ExecutorService eservice = Executors.newSingleThreadExecutor();
        while (1 == 1) {
            String stringParams = getFilesNeedToImportAsString();
            if (stringParams.trim().isEmpty()) {
                long l1 = System.currentTimeMillis() - l;
                System.out.println("all time" + l1 / 1000);
                System.exit(100);
            }
            RunTask runTask = new RunTask();
            runTask.setRunParams(SystemInfo.RUN_COMMAND + stringParams);
            Future<Object> objectFuture = eservice.submit(runTask);
            while (!objectFuture.isDone()) {
                System.out.println("waiting the task running");
                Thread.sleep(500);
            }
        }

しかし、processBで例外が発生した場合、両方のプロセス(processA、processB)が停止しているように見えます。これは、processBで実行されるコードです。

public Object call() {
    try {
        MutationResult result = mutator.execute();
        return "ok";
    } catch (Exception exp) {
        exp.printStackTrace();
        System.out.println("error on " + Thread.currentThread().getName() + "failed begin retry " + (++retryCount));
        call();
        System.out.println(retryCount + " completed");
        return "ok";
    }

}

processBを(コマンドラインで)スタンドアロンで実行した場合、それは決して起こりません。または、この問題が発生した場合、taskmanagerを使用してproceesA(呼び出し先)を強制終了し、processBは実行を継続します。

誰かが私にこの問題の解決策を教えてください!

4

3 に答える 3

2

objectFuture isDoneメソッドが完了するのを待ちます。ドキュメントによると:

isDone:このタスクが完了した場合はtrueを返します。完了は、通常の終了、例外、またはキャンセルが原因である可能性があります。これらすべての場合、このメソッドはtrueを返します。

例外が発生したときにprocessBのコードを確認すると、call()再帰的に再度実行されます。これをエラー再試行メカニズムとして実行することは理解していますが、これは2つの主な理由から非常に悪い考えです。-例外が続く場合は、が発生することになりますStackOverflowException。-の条件はいずれisDoneも満たされません。

より良い代替策は、再試行の最大数を定義して、を実行してみることmutator.execute()です。エラーが続く場合は、例外をスローして実行を終了します。

もう1つのオプションは、processBが終了するまで最大時間待機してから、を呼び出してタスクの実行をキャンセルすることobjectFuture.cancel(true)です。

processAに関するいくつかのコメント:文字列としてインポートする必要があるいくつかのファイルのように見えるものRunTaskは使用しません。runParamsまた、非推奨のメソッドであるを使用readLine()します。DataInputStream代わりに、でラップされてから-でラップされたInputStream(例BufferedInputStream)を使用してから、を呼び出します。InputStreamReaderBufferedReaderreadLine()BufferedReader

于 2012-06-09T09:29:48.997 に答える
1

execを生成するときに問題が発生したのは、エラーが発生し、ErrorStreamを読み取るスレッドを設定していない場合、ErrorStreamバッファーがいっぱいになる可能性があることです。その時点で、すべてが停止して待機します。 ErrorStreamバッファからテキストの一部をクリアします。プロセスBは、私が書き込むまでエラーを書き込むことができず、プロセスAはプロセスBが終了するのを待っています。

私の経験の最終結果:exec()を実行するときは、常にInputStreamとErrorStreamのそれぞれを読み取るスレッドを設定してください。

于 2012-06-09T05:17:12.930 に答える
1

printStackTrace標準出力ではなく、標準エラーで出力されます。標準エラーも読み取る必要があります(これは注意が必要です。ストリームごとに1つずつ、2つのスレッドが必要です)。または、代わりに標準出力に出力します(printStackTrace(System.out))。

于 2012-06-09T05:18:23.663 に答える