如何在 Java 中中断/终止挂起的线程?

use*_*927 1 java concurrency multithreading

我试图弄清楚线程在 Java 中是如何工作的。我想了解如何中断为运行另一个终端进程而创建的线程。我有以下线程:

  • 主线程
  • swing 线程- 管理 GUI
  • 终端线程- 运行终端进程

终端进程需要将其输出提供给终端线程的输入流。我已经设法通过 while 循环来做到这一点。然而,如果终端进程被卡住(例如等待用户输入),这样做实际上会挂起线程。

我的问题有两个:

  1. 如何中断终端线程?(参见下面我的代码)
  2. 如果我通过主线程和 swing 线程关闭我的应用程序,这会关闭终端线程吗?我一直以这种方式关闭我的应用程序......幽灵线程会继续运行吗?如果是这样,我该如何驱除它?

下面的代码是运行线程的可运行实现,该线程依次运行终端进程:

public void run(){
    ProcessBuilder pb=new ProcessBuilder("Enter a terminal process that hangs here");
    pb.redirectErrorStream(true);

    Process pr;
    try {
        pr = pb.start();
        BufferedReader in = new BufferedReader(new 
        InputStreamReader(pr.getInputStream()));
        String line;
        try {
            while ((line = in.readLine()) != null && !Thread.currentThread().isInterrupted()) {
                System.out.println(line);
            }
            pr.waitFor();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("ok!");
        in.close();
        //System.exit(0);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

我期待!Thread.currentThread().isInterrupted()停止循环并提供中断。但是,当我通过以下代码调用中断时,它不会中断:

JButton btnKillThreads = new JButton("Kill Threads");
btnKillThreads.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        for (Thread thread : threads){
            thread.interrupt();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

为了完整性,这里是创建线程的代码:

JButton btnStartConversion = new JButton("Start Thread");
btnStartConversion.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Runnable rt = new Thread1();
        Thread t = new Thread(rt);
        t.start();
        threads.add(t);
    }
});
Run Code Online (Sandbox Code Playgroud)

Sla*_*hev 5

我认为你有一个好的开始。唯一的问题是这Thread.interrupt()不会停止这个过程。如果线程被阻塞in.readLine(),则在进程产生输出并且线程有机会检查 之前,它不会退出isInterrupted()

如果您想停止该过程,除了调用之外,Thread.interrupt()您还需要调用Process.destroy()

class MyRunnable implements Runnable {

   private Process pr; 

   public void run() {

      // ...

      pr = pb.start();
   }

   public shutdown() {
      pr.destroy();
      interrupt();
   }
}
Run Code Online (Sandbox Code Playgroud)

您需要注册您的线程,而不是在列表中注册线程MyRunnable并调用shutdown()它。

至于线程在 上的行为System.exit(),所有线程都会被销毁。但是,使用System.exit()被认为是不好的形式,因为它终止应用程序而不给线程正常关闭的机会。合理的工程实践是考虑优雅的关闭并System.exit()仅将其作为最后的手段。