我在用户点击用户界面上的“停止”按钮时尝试安全地停止多个线程时创建了一个小例子(如下)。然而,似乎在这次尝试之后,线程似乎仍在运行。你能指点我正确的方向吗?
修改
感谢大家的评论,只是为了跟帖子一起,我用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();
}
}
}
答案 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以终止,目标线程定期检查该标志。说实话,这种方法几乎是一个手动中断系统。