Java 阻止进程InputStream上的读取时停止gobbler线程
我有一个gobbler,它读取进程的输出 在这种情况下,我们使用进程的PID和外部Windows taskkill命令以编程方式终止进程 这是一个16位DOS进程 我们之所以使用taskkill,是因为它是一个DOS 16位进程和进程。destroy forcely()不使用它,因为它位于ntvdm子系统中,最好的方法是获取PID并使用“taskkill/T/F”,它确实会杀死它和任何子系统 通常,我们的DOS 16位(或32位)进程没有问题。这个有一些文件锁。尤其重要的是,我们要确保操作系统释放锁是死的 我们在杀戮前后关闭所有溪流 在调用taskkill之前,我们尝试刷新并关闭执行器中的所有流:in、out、err。调用taskkill后,我们通过重新关闭所有流来验证它们是否已关闭 我们在杀死所有狼人后调用Thread.interrupt() 现在,在杀戮成功后(操作系统中也确认了这一点),gobbler仍在运行,它不会响应Thread.interrupt() 我们甚至做了最后一搏。停下来(喘息!) 而且,我们已经对它调用了Thread.stop(),它仍然在读取阶段等待 因此,我们似乎无法阻止进程流上的std out和std in吞噬器 我们知道Thread.stop()已被弃用。为了安全起见,我们抓住了死亡 然后清洁所有监视器,然后重新旋转。然而, ThreadDeath实际上从未抛出,线程只是继续 正在等待inputStream.read。。 因此,Thread.stop在本例中被弃用是一个没有实际意义的问题 ... 因为它什么都不做。 这样就不会有人炒我的鱿鱼,让我有一个清白的良心, 我们已经从生产代码中删除了Thread.stop() 线程不中断并不奇怪,因为这只发生在一些InputStreams上,并且并非所有读取都是不可破坏的。但我很惊讶,当调用Thread.stop时,线程不会停止 线程跟踪显示 线程跟踪显示main-in和main-er(进程的两个输出)即使在流关闭、线程中断和调用last-ditch thread.stop之后仍在运行 任务已经结束,为什么要关心空闲的阻塞吞噬者呢? 这并不是说我们在乎狼吞虎咽的人不会放弃。但是我们不喜欢运行那些堆积起来阻塞系统的线程。此特定进程由Web服务器调用,然后。。在死机进程上,可能有数百个处于阻塞状态的空闲线程 我们尝试了两种方式启动流程,没有任何区别…Java 阻止进程InputStream上的读取时停止gobbler线程,java,multithreading,interrupt,kill-process,taskkill,Java,Multithreading,Interrupt,Kill Process,Taskkill,我有一个gobbler,它读取进程的输出 在这种情况下,我们使用进程的PID和外部Windows taskkill命令以编程方式终止进程 这是一个16位DOS进程 我们之所以使用taskkill,是因为它是一个DOS 16位进程和进程。destroy forcely()不使用它,因为它位于ntvdm子系统中,最好的方法是获取PID并使用“taskkill/T/F”,它确实会杀死它和任何子系统 通常,我们的DOS 16位(或32位)进程没有问题。这个有一些文件锁。尤其重要的是,我们要确保操作系统释
run(working, "cmd", "/c", "start", "/B", "/W", "/SEPARATE", "C:\\workspace\\dotest.exe");
run(working, "cmd", "/c", "C:\\workspace\\dotest.exe");
狼吞虎咽的人是这样读的:
try (final InputStream is = inputStream instanceof BufferedInputStream
? inputStream : new BufferedInputStream(inputStream, 1024 * 64);
final BufferedReader br = new BufferedReader(new InputStreamReader(is, charset))) {
String line;
while ((line = br.readLine()) != null) {
lineCount++;
lines.add(line);
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
throw new InterruptedException();
}
}
eofFound = true;
}
我们的破坏者在taskkill之后在gobbler线程上调用此命令:
int timeLimit = 500;
t.interrupt();
try {
t.join(timeLimit);
if (t.isAlive()) {
t.stop();
// we knows it's deprecated but we catch ThreadDeath
// then clean any monitors and then rethrow ThreadDeath
// But ThreadDeath never in fact gets thrown and the thread
// just keeps on waiting on inputStream.read ..
logger.warn("Thread stopped because it did not interrupt within {}ms: {}", timeLimit, t);
if (t.isAlive()) {
logger.warn("But thread is still alive! {}", t);
}
}
} catch (InterruptedException ie) {
logger.info("Interrupted exception while waiting on join({}) with {}", timeLimit, t, ie);
}
这是日志输出的一个片段:
59.841 [main] INFO Destroying process '5952'
04.863 [main] WARN Timeout waiting for 'Close java.io.BufferedInputStream@193932a' to finish
09.865 [main] WARN Timeout waiting for 'Close java.io.FileInputStream@159f197' to finish
09.941 [main] DEBUG Executing [taskkill, /F, /PID, 5952].
10.243 [Thread-1] DEBUG SUCCESS: The process with PID 5952 has been terminated.
10.249 [main] DEBUG java.lang.ProcessImpl@620197 stopped with exit code 0
10.638 [main] INFO Destroyed WindowsProcess(5952) forcefully in 738 ms.
11.188 [main] WARN Thread stop called because it did not interrupt within 500ms: Thread[main-in,5,main]
11.188 [main] WARN But thread is still alive! Thread[main-in,5,main]
11.689 [main] WARN Thread stop because it did not interrupt within 500ms: Thread[main-err,5,main]
11.689 [main] WARN But thread is still alive! Thread[main-err,5,main]
注意:在调用taskkill之前,进程std out和std err不会关闭。但是在taskkill之后,它们会被手动关闭(因为成功,所以不会显示在日志中)。Thread.stop()已被弃用,这是有充分理由的。请在代码段中包含listen()方法的代码。但最有可能的问题是使用不间断I/O,请查看如何使inputstream可中断。线程跟踪显示它被卡在读取上。Listen只是将该行添加到ArrayList。我将补充这一点,以澄清这一点。Thread.stop只是最后一次尝试,看看什么可能有效。@PawelVeselov您提供的链接只适用于SocketInputStream。并非所有输入流都可以中断。进程InputStream似乎不是——至少不是这个。事实上,流是关闭的,即使这样也不会停止当前的读取。这应该是不必要的。如果进程已退出,则没有可阻止读取的内容。你的观察有问题。日志中的前两条警告消息是从哪里打印的?@EJP我们希望是这样。你想要一个logmein会话,你可以自己看。两个读卡器卡在read中,流关闭,线程中断并停止。尤普斯。的确顺便说一句,我在DOS、Windows和Java上工作了多年,从事系统编程。流关闭的所有日志记录都显示成功。所以,问题是,进程输入流是可中断的吗?如果是这样,taskkill会否定这种能力吗?对不起,这是一个涂鸦器,否则我不会把它贴在这里。