Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何停止由线程控制的进程?_Java_Multithreading - Fatal编程技术网

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

Java 如何停止由线程控制的进程?,java,multithreading,Java,Multithreading,我有一个Java应用程序,它使用一些参数启动另一个应用程序。Java应该能够同时继续,并在用户输入后终止另一个应用程序。 通过阅读本文,我发现我应该使用Thread.Interupt,因为Thread.Stop已不推荐使用。 在你的线程上,它会抛出一个InterruptedExection。因此,我得到的是: public class ProcessExecutor extends Object implements Runnable { private volatile int id;

我有一个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");        
}

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