Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 阻止进程InputStream上的读取时停止gobbler线程_Java_Multithreading_Interrupt_Kill Process_Taskkill - Fatal编程技术网

Java 阻止进程InputStream上的读取时停止gobbler线程

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位)进程没有问题。这个有一些文件锁。尤其重要的是,我们要确保操作系统释

我有一个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服务器调用,然后。。在死机进程上,可能有数百个处于阻塞状态的空闲线程

我们尝试了两种方式启动流程,没有任何区别…

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会否定这种能力吗?对不起,这是一个涂鸦器,否则我不会把它贴在这里。