如何停止线程控制的进程?

时间:2012-01-11 13:21:31

标签: java multithreading

我有一个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()阻止,以阻止我必须直接停止Process,然后取消阻止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");        
}

4 个答案:

答案 0 :(得分:0)

您必须在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

答案 1 :(得分:0)

中断线程只有在处于特定状态时才有效,通常是在不主动处理数据时完成的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(),但如果您在流上写入一行一行应该没有区别办法。等待的时间显然是随意的。

答案 2 :(得分:0)

我建议更优雅的方式来阻止线程。在run方法中,您有以下代码

 while ((line=input.readLine()) != null) {
                System.out.println("ProcessExecutor: " + line);
            }

ProcessExecutor中,添加一个布尔字段,并附带其getter和setter。

private Boolean stop = false;

并在条件状态下检查相同的标志。

while (((line=input.readLine()) != null) && !stop) {
                    System.out.println("ProcessExecutor: " + line);
                }

StopAllProcesses()方法中,在stop=true个实例上设置ProcessExecutor。这将导致run()方法返回并正常停止线程。

答案 3 :(得分:0)

正如我在评论中所说。我认为中断线程阻止读取一行的唯一方法是杀死线程读取的进程。正如阻止线程阻塞读取套接字的唯一解决方案是关闭套接字。

在您的线程中添加一个破坏该过程的方法。