如何安全地停止多个线程?

时间:2012-02-01 23:29:37

标签: java

我在用户点击用户界面上的“停止”按钮时尝试安全地停止多个线程时创建了一个小例子(如下)。然而,似乎在这次尝试之后,线程似乎仍在运行。你能指点我正确的方向吗?

修改

感谢大家的评论,只是为了跟帖子一起,我用volatile boolean标志修改了下面的代码,看起来工作正常,直到我做了一些I / O操作。
如果我添加I / O操作,即使调用fstream.close然后调用stop函数来打开boolean标志,线程似乎也在运行...(描述程序以仔细检查线程是否仍在运行) 。 为了处理打开的文件,我还需要做任何其他事情,并最终停止线程吗? 再次感谢。

已修复且正常工作的代码。

class MultiThreadExample implements Runnable {
    private static final MultiThreadExample threadObj = new MultiThreadExample();
    ArrayList<Thread> threadList = new ArrayList<Thread>();

    public static MultiThreadExample getInstance() {
      return threadObj;
    }

    public void tester() {
      File file = new File("data/");
      File[] files = file.listFiles();
      for (int i = 0; i < files.length; i++) {
        Thread thread = new Thread(new ThreadedCrawler(), files[i].toString());
        thread.start();
        threadList.add(thread);
      }
    }

    public void run() {
      try {
        ProgramTester.getInstance().doSomething();          
      }
      finally { 
        do other stuff 
      }
    }


    public synchronized void stop() throws IOException {
      for (Thread threads : threadList) 
         threads.interrupt();
    }

    public void doSomething() {
      FileInputStream fstream = new FileInputStream(file);
      BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
      String inLine;
      while (((inLine = br.readLine()) != null) &&  !Thread.currentThread().isInterrupted()) {
        do something...
           for()...
               ....
               }
    }
}

public class GuiExample extends JFrame {
    ....
    public void mousePressed(MouseEvent e) {
      try {
        MultiThreadExample.getInstance().stop();
      }
      catch (InterruptedException e1) {
        e1.printStackTrace();
      }
    }
}

3 个答案:

答案 0 :(得分:4)

interrupt()不会停止该线程(请参阅API)。处理此问题的首选方法是使run()方法定期检查标志并在设置时退出(当然,当您要终止线程时设置标志)。

stop()杀死了这个帖子,但它已被弃用了很长时间(有充分的理由)。

同样的问题here

更新

由于您检查doSomething()之外的标志,它将在方法完成之前退出,因此长时间运行的任务(如文件io)将继续。

将检查移至br.readLine()上的循环,正如其他人所建议的那样,使用interrupt() / isInterrupted()可能会更好,因为它也会阻止在io上阻止的线程。

答案 1 :(得分:1)

interrupt()停止线程, iff 它们会定期检查isInterrupted()或中断()。现在这是常见做法 - 最好是IMO,按照@Dmitri的建议定期检查标志。

但是,为了实现这一点,您需要确保线程/ Runnables定期检查其中断状态。

答案 2 :(得分:0)

在Java中停止线程是一个合作的过程。

首先必须有一种机制来表示线程停止的欲望(由另一个线程调用)。 Thread.interrupt是一种内置的方法。

其次,目标线程必须合作并遵守“停止”。发出任何信号。

一种方法是让线程在目标线程上调用interrupt。目标线程应定期调用Thread.interrupted,如果返回true则正常终止。

另一种方法是使用一个volatile布尔标志,线程设置为true以终止,目标线程定期检查该标志。说实话,这种方法几乎是一个手动中断系统。