[英]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.