【问题标题】:How to terminate a process initiated by java如何终止由java启动的进程
【发布时间】:2018-09-30 10:08:49
【问题描述】:

我正在使用 p = Runtime.getRuntime().exec("myScript.sh");作为按钮 A 的 addActionListener(new ActionListener() 的 actionPerformed(ActionEvent evt) 的一部分。

我想有办法终止进程。我试图创建另一个调用 p.destroy() 的按钮(按钮 B)。但是,看起来在单击按钮 A 后,它会启动进程,并且只有在进程完成之前,我才能单击 GUI 上的其他按钮(包括右上角的关闭按钮)。所以我不能中途终止进程。

有什么方法可以终止进程吗?或者有什么方法可以在按钮 A 启动的进程仍在运行时单击其他按钮?

我注释掉了 p.waitFor();点击 btnRun 后我仍然无法点击其他按钮

    private Process p;
    btnRun.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            String s;
            try {
                p = Runtime.getRuntime().exec(command);
                BufferedReader br = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
                while ((s = br.readLine()) != null)
                    System.out.println(s);
                //p.waitFor();
                //System.out.println ("exit: " + p.exitValue());
                //p.destroy();
            } catch (Exception e) {}
        }
     });

    btnTerminate.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            p.destroy();
        }
    });

【问题讨论】:

  • 看来你的GUI线程被exec启动的进程阻塞了。你确定你没有在这个过程中打电话给waitFor()吗?无论如何,MCVE 会有很大帮助。
  • 从声音来看,你正在阻塞事件调度线程,也许像 this examplethis example 这样的东西可以提供帮助
  • @MadProgrammer 是的,你是对的。我正在阻止 EDT。我看了你的例子。我很难完全理解,但它绝对是一个很棒的工具。 (摇摆人)!我实施了 Mathem 的解决方案。但是非常感谢!
  • @WenhaoGeng 您还应该支持ProcessBuilder 而不是Runtime#exec,因为它更具可配置性,并允许您将错误流与输入流合并 - 这是 MathM 的答案忽略的内容

标签: java swing user-interface process


【解决方案1】:

来自 BufferedReader 的 while 循环处理行也会阻塞 EDT。 BufferedReader 将尝试读取流,直到它关闭,并且在 Process 完成时将其关闭。在此之前,EDT 被readLine() 阻止。您必须在另一个线程中处理这些行。

看这个例子

class InStreamPrinter extends Thread {
    InputStream is;

    InStreamPrinter(InputStream is) {
        this.is = is;
    }

    @Override
    public void run() {
        try (InputStreamReader isr = new InputStreamReader(is); 
            BufferedReader br = new BufferedReader(isr);) {
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然后只需将输入流从 Process 传递到此 Thread 并启动它。

...
p = Runtime.getRuntime().exec(command);
new InStreamPrinter(p.getInputStream()).start();
...

【讨论】:

  • 成功了!非常感谢。你太棒了,直接发现了我的问题所在!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多