我有一个servlet,它在doGet()中创建一个新的Action对象,该对象使用exec()来运行外部进程。可能会同时向servlet发出多个请求,因此我可能会有几个Action对象,其中每个对象同时运行一个外部进程。偶尔当发生这种情况时,我发现一个进程的输出与其他进程的输出混淆。
每个Action创建一个唯一的临时目录,并以此作为当前目录运行该进程。然后,单独的线程将进程的输出流读入字符串缓冲区。 Action对象执行的代码看起来基本上是这样的:
Process proc = null;
ReaderThread stdout = null;
ReaderThread stderr = null;
StringBuffer buff = new StringBuffer();
int exit = -1;
try {
//
// Run the process
//
proc = Runtime.getRuntime().exec(command,null,directory);
//
// Read the output from the process
//
stdout = new ReaderThread(proc.getInputStream(),buff);
stderr = new ReaderThread(proc.getErrorStream(),buff);
stdout.start();
stderr.start();
//
// Get the exit code
//
exit = proc.waitFor();
//
// Wait for all the output to be read
//
stdout.join();
stderr.join();
}
catch (InterruptedException e) {
if (proc != null) {
proc.destroy();
}
}
catch (Exception e) {
buff.append(e.getClass() + ": " + e.getMessage());
if (proc != null) {
proc.destroy();
}
}
因此每个请求使用一个单独的Action对象来运行一个进程,并且它有自己的StringBuffer" buff"该过程的输出由两个ReaderThreads累积。但我发现,当两个请求同时运行两个进程时,一个的输出有时会在运行另一个的线程的StringBuffer中结束,并且两个servlet请求中的一个将看到输出打算用于另一个。它的行为基本上就像Runtime.exec()提供了一个全局管道,所有进程的输出流都连接到该管道。
ReaderThread看起来像这样:
public class ReaderThread extends Thread {
private BufferedReader reader;
private StringBuffer buffer;
public ReaderThread (InputStream stream, StringBuffer buffer) {
this.reader = new BufferedReader(new InputStreamReader(stream));
this.buffer = buffer;
}
@Override
public void run () {
try {
String line;
while ((line = reader.readLine()) != null) {
synchronized (buffer) {
buffer.append(line + "\n");
}
}
}
catch (IOException e) {
synchronized (buffer) {
buffer.append(e.getMessage() + "\n");
}
}
}
}
有人可以建议我可以做些什么来解决这个问题吗?
答案 0 :(得分:0)
使用ThreadLocal变量存储每个线程的输出。
答案 1 :(得分:0)
这是解释,部分是一个警示故事:
咄。
我生命中又过了两天!#/ p>
新年快乐......