繁体   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