簡體   English   中英

如何停止線程控制的進程?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM