3

xのインスタンスが与えられた場合、プロセスの標準の入力と出力をリダイレクトできるように、別のプロセスでCallable<T>実行するにはどうすればよいですか?xたとえば、?Processからを構築する方法はありCallableますか?Executor入出力を制御する規格はありますか?

[更新]Callable新しいスレッドではなく、新しいプロセスで実行することは重要ではありません。私が欲しいのは、Callableインスタンスを「ハーネス」に入れて、そのstdin/stdoutを制御できるようにすることです。AFAIK、これは新しいプロセスを必要とします。

4

4 に答える 4

2

より一般的には:

グローバル変数AとBを利用するCallableのインスタンスxが与えられた場合、xがAとBの「元の」値ではなく、AとBのカスタム値を参照するようにxを同時に実行するにはどうすればよいですか?

そして最良の答えは、グローバル変数を使用しないことです。依存性はそのようなものを注入します。Callableを拡張し、メソッドsetStdIn、setStdOut(および必要に応じてsetStdErr)を追加します。

これがあなたが探している答えではないことは知っていますが、これについて私が見た解決策はすべて新しいプロセスを必要とし、Callableを新しいプロセスに取り込む唯一の方法はCallableのコードを変更することですシリアル化可能であるか、クラス名またはその他のハックを提供するため、厄介で脆弱なソリューションを提供する変更を加える代わりに、正しく実行してください*

*「正しい」とは、広く受け入れられている依存性注入のパターンを使用して、緩い結合を提供することです。YMMV

更新:コメント1への応答:新しいインターフェースは次のとおりです。

import java.io.InputStream;
import java.io.PrintStream;
import java.util.concurrent.Callable;


public interface MyCallable<V> extends Callable<V> {
  void setStdIn(InputStream in);
  void setStdOut(PrintStream out);  
}

タスクは次のようになります。

import java.io.InputStream;
import java.io.PrintStream;


public class CallableTask implements MyCallable<Object> {

    private InputStream in = System.in;
    private PrintStream out = System.out;

    public void setStdIn(InputStream in) {
        this.in = in;
    }

    public void setStdOut(PrintStream out) {
        this.out = out;
    }

    public Object call() throws Exception {
        out.write(in.read());
        return null;
    }

}

プロセスの必要はありません。すべてのソリューション(プロセスを使用するソリューションでも)は、ほぼ確実に、何らかの方法でCallablesのコードを変更する必要があります。これが最も簡単です(System.outをthis.outに置き換えるだけです)。

于 2008-12-04T23:53:07.880 に答える
1

上記のパラメータ化、依存性注入、またはあなたがそれを呼びたいものを使用して、コードを構造化するように努めてください。シングルトンに扮したり、悪いライブラリに隠されていたりしても、静力学は避けてください。

あなたがあなたの使用法を削除したくない場合System.in/out/errは運がいいです。これらは、でグローバルに設定できますSystem.set(In/Out/Err)。個々のスレッドごとに異なる方法でストリーミングできるようにするにはThreadLocal、委任先のターゲットを見つけるために使用する実装を設定します。スレッドローカルは一般的に悪ですが、不幸な状況で役立つ場合があります。

明確化から、元のポスターは別のプロセスを作成する必要がないようです。

于 2008-12-05T11:52:42.420 に答える
1

stdin/stdout はシステム全体でリダイレクトできますが、単一のスレッドでリダイレクトできるかどうかはわかりません。常に System. ( System.out を別のストリームに移動させることはできますが、トレースを文字列として取得するメソッドが存在する前に、それを使用してスタック トレースをキャッチしました)

stdin/stdout をリダイレクトし、callable を実行してからリダイレクトすることもできますが、リダイレクト中に System.out を使用するものがあれば、それも新しいファイルに移動します。

そのルートに行きたい場合、メソッドは System.setIn() と System.setOut() (および System.setErr()) になります。

于 2008-12-05T00:47:19.020 に答える
0

ProcessBuilderクラスを見てください。これにより、起動するプロセスのstdoutとstderrをキャプチャするオプションが提供されます。

Callableを実行するMainクラスを作成し、ProcessBuilderを使用して別のjvmとして起動できます。Mainクラスは、呼び出し可能オブジェクトのクラス名をコマンドライン入力パラメーターとして受け入れ、Class.forName()およびClass.newInstance()を使用してロードできます。

別の方法として、特定の呼び出し可能なインスタンスを実行する場合は、他のプロセスを起動する前にインスタンスをファイルにシリアル化することです(これは、2つのプロセス間の通信の非常に大雑把な形式になります)。

問題は、なぜあなたはそれをしたいのですか?呼び出し可能オブジェクトを別のスレッドで実行することはできませんか?java.util.concurrentには、そのための便利なスレッドプールがいくつかあります。

于 2008-12-04T23:34:37.623 に答える