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

时间:2014-10-30 08:07:01

标签: java multithreading concurrency

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

  • 主要帖子
  • 摆动线程 - 管理GUI
  • 终端广告 - 运行终端流程

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

我的问题有两个:

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

    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();
        }
    }
    

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

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

    以下是为完整性创建线程的代码:

    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);
        }
    });
    

2 个答案:

答案 0 :(得分:2)

我认为你有个好的开始。唯一的问题是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();
   }
}

您需要注册MyRunnable并在其上调用shutdown(),而不是在列表中注册该帖子。

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

答案 1 :(得分:0)

将while循环中的条件更改为:

while ((line = in.readLine()) != null && !Thread.currentThread().isInterrupted()) {
    System.out.println(line);
}