Java 如何停止由线程控制的进程?
我有一个Java应用程序,它使用一些参数启动另一个应用程序。Java应该能够同时继续,并在用户输入后终止另一个应用程序。 通过阅读本文,我发现我应该使用Thread.Interupt,因为Thread.Stop已不推荐使用。 在你的线程上,它会抛出一个InterruptedExection。因此,我得到的是:Java 如何停止由线程控制的进程?,java,multithreading,Java,Multithreading,我有一个Java应用程序,它使用一些参数启动另一个应用程序。Java应该能够同时继续,并在用户输入后终止另一个应用程序。 通过阅读本文,我发现我应该使用Thread.Interupt,因为Thread.Stop已不推荐使用。 在你的线程上,它会抛出一个InterruptedExection。因此,我得到的是: public class ProcessExecutor extends Object implements Runnable { private volatile int id;
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");
}
您必须在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");
}
有关更多详细信息,请参阅。中断线程仅在线程处于特定状态时有效,通常是在等待调用期间完成的,而等待调用是在不主动处理数据时完成的 如果希望线程在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实际上检查单个字符,所以应该使用连续读取而不是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方法返回并优雅地停止线程。正如我在评论中所说。我认为中断线程阻塞读取行的唯一方法是终止线程读取的进程。正如在套接字上中断线程阻塞读取的唯一解决方案是关闭套接字
向线程添加破坏进程的方法。线程和进程是两码事。要杀死进程,请调用其destroy方法。中断等待进程结束的线程不会终止进程。如果抛出InterruptedException,则我可以通过proc.destroy;终止进程;。但是为什么InterruptedException没有被抛出呢?可能是因为线程在读取进程输入流中的行时被阻塞了,而这个阻塞调用是不可中断的。这与Jeremiah Orr的解决方案完全相同,并且具有相同的缺陷:如果线程在尝试读取时被阻塞,它不会退出线程。是的!OP应该明确提到阻塞条件。我想这就是OP想要的。我不知道readLine阻止了它。我只看到线程没有停止。只是尝试了一下,并有相同的问题。线程在readLine中被阻止。正确地说,这就是我刚才所做的,它是有效的:用解决方案更新问题以供将来参考。阻止发送方进程以停止接收方?这是一个糟糕的解决方案。至少,您可以发送一个流的结尾,以便接收者干净地退出。当然,最好的解决方案是首先不要无限期地阻塞。读取方法都是阻塞方法。除了无限期封锁之外,没有其他选择。如果这个过程可以更优雅地停止,那么它当然应该停止。但这是特定于进程的。而且,无论如何,OP希望在线程中断时销毁进程。
while (((line=input.readLine()) != null) && !stop) {
System.out.println("ProcessExecutor: " + line);
}