[英]How do I stop a process controlled by a thread?
我有一个Java应用程序,它可以使用一些参数启动另一个应用程序。 Java应该能够同时继续运行,并在用户输入后杀死其他应用程序。 阅读此书后,我发现我应该使用Thread.Interupt()
因为不推荐使用Thread.Stop()
。 在您的线程上它将抛出InterruptedExection。 所以我有:
public class ProcessExecutor extends Object implements Runnable {
private volatile int id;
private String message;
private Process proc = null;
public ProcessExecutor(int id, String message) {
this.id = id;
this.message = message;
}
public int GetId() {
return id;
}
public void run() {
try {
String[] cmd = new String[4];
cmd[0] = "path to some app";
cmd[1] = id;
cmd[2] = message;
Runtime rt = Runtime.getRuntime();
proc = rt.exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line=null;
while ((line=input.readLine()) != null) {
System.out.println("ProcessExecutor: " + line);
}
int exitVal = proc.waitFor();
System.out.println("ProcessExecutor: Exited with error code " + exitVal);
} catch(InterruptedException ex) {
System.out.println("ProcessExecutor: stopping");
if (proc != null) {
proc.destroy();
proc = null;
}
} catch(Exception e) {
System.out.println("ProcessExecutor: exception: " + e.toString());
e.printStackTrace();
}
}
}
由以下方式处理:
private List<Thread> activeProccesses = new ArrayList<Thread>();
public void StartProcess(int id, String message) {
System.out.println("StartProcess: id=" + id + ", message='" + message + "'");
StopAllProcesses();
ProcessExecutor proc = new ProcessExecutor(id, message);
Thread procThread = new Thread(proc);
activeProccesses.add(procThread);
procThread.start();
}
public void StopAllProcesses() {
System.out.println("Stopping all processes");
Iterator<Thread> it = activeProccesses.iterator();
while (it.hasNext()) {
Thread procThread = it.next();
if (procThread.isAlive()) {
procThread.interrupt();
}
it.remove();
}
System.out.println("Stopping all processes: done");
}
procThread.interrupt()
如何执行,但是catch(InterruptedException ex)
从未命中。
为什么会这样,我该如何解决?
编辑:结论
input.readLine()
证明,该线程被input.readLine()
阻止了,以便停止,我不得不直接停止Process
,然后再input.readLine()
阻塞input.readLine()
。
public class ProcessExecutor extends Thread {
private volatile int id;
private String message;
private volatile Process proc = null;
public ProcessExecutor(int id, String message) {
this.id = id;
this.message = message;
}
public int GetId() {
return id;
}
public void StopProc() {
if (proc != null) {
proc.destroy();
}
}
public void run() {
try {
String[] cmd = new String[4];
cmd[0] = "path to some app";
cmd[1] = id;
cmd[2] = message;
Runtime rt = Runtime.getRuntime();
proc = rt.exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line=null;
while ((line=input.readLine()) != null) {
System.out.println("ProcessExecutor: " + line);
}
int exitVal = proc.waitFor();
proc = null;
System.out.println("ProcessExecutor: Exited with error code " + exitVal);
} catch(Exception e) {
System.out.println("ProcessExecutor: exception: " + e.toString());
StopProc();
}
}
}
private List<ProcessExecutor> activeProccesses = new ArrayList<ProcessExecutor>();
public void StartProcess(int id, String message) {
System.out.println("StartProcess: id=" + id + ", message='" + message + "'");
StopAllProcesses();
ProcessExecutor proc = new ProcessExecutor(id, message);
activeProccesses.add(proc);
proc.start();
}
public void StopAllProcesses() {
System.out.println("Stopping all processes");
Iterator<ProcessExecutor> it = activeProccesses.iterator();
while (it.hasNext()) {
ProcessExecutor proc = it.next();
proc.StopProc();
it.remove();
}
System.out.println("Stopping all processes: done");
}
您必须在ProcessExecutor中明确检查中断条件; InterruptedException不会自动引发。 像这样:
public class ProcessExecutor extends Object implements Runnable {
public void run() {
try {
//other code....
while ((line=input.readLine()) != null) {
System.out.println("ProcessExecutor: " + line);
if (Thread.interrupted()) {
// We've been interrupted!
throw new InterruptedException("....");
}
}
} catch(InterruptedException ex) {
System.out.println("ProcessExecutor: stopping");
}
有关更多详细信息,请参见http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html 。
中断线程仅在处于特定状态时才起作用,通常是在不主动处理数据时完成的wait()
调用期间完成的。
如果您希望线程在readLine()
调用之间死掉,则可以在while检查中检查interrupted()
而不是使用try-catch。
编辑:解决您的问题的最好方法是
while (true)
{
if (input.ready())
{
line = input.readLine();
System.out.println("ProcessExecutor: " + line);
} else {
try { Thread.sleep(100); } // time to wait in ms
catch (InterruptedException ie) { break; }
}
}
由于ready()
实际上检查单个字符,因此您应该使用连续的read()
而不是readLine()
,但是如果您一次在流上写入一行,则这种方式应该没有区别。 等待的时间显然是任意的。
我建议使用更优雅的方式来停止线程。 在run方法中,您具有以下代码
while ((line=input.readLine()) != null) {
System.out.println("ProcessExecutor: " + line);
}
在ProcessExecutor
,添加一个布尔字段以及其getter和setter。
private Boolean stop = false;
并在while条件下检查相同的标志。
while (((line=input.readLine()) != null) && !stop) {
System.out.println("ProcessExecutor: " + line);
}
在StopAllProcesses()
方法中,在ProcessExecutor
实例上设置stop=true
。 这将导致run()
方法返回并正常停止线程。
正如我在评论中所说。 我认为中断线程读取行的唯一方法是杀死该线程读取的进程。 就像中断套接字上读取的线程的唯一方法一样,就是关闭套接字。
在您的线程中添加一个破坏进程的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.