我有一个类将以无限循环启动一个Runnable。在某个时候,我想关闭程序,并且希望以一种干净的方式来做到这一点(例如,确保在执行结束时线程将刷新某个缓冲区以输出文件等)。我该怎么做?Java等待runnable完成
注:在评论中我写了// Version 1
和// Version 2
。那是因为我试了两个版本,但都没有工作,我不断得到一个InterruptedException。
主类:
public class MainClass {
private static Thread myThread;
private static MyRunnable myRunnable;
private static Logger logger;
public static void main(String[] args) {
...
myRunnable = new MyRunnable(logger);
myThread = new Thread(myRunnable);
myThread.start();
...
}
private static void shutDown() {
logger.debug("Shut down everything.");
if(myRunnable != null){
myRunnable.shutdown();
try {
myThread.join();
logger.debug("Runnable Stopped");
} catch (InterruptedException e) { // Always failing here
e.printStackTrace();
}
}
// Now stop logger and other things
logger.debug("Shutdown other stuff");
...
logger.debug("Shutdown logger");
Configurator.shutdown((LoggerContext)LogManager.getContext());
System.out.println("Done");
}
}
运行的类:
public class MyRunnable implements Runnable {
private AtomicBoolean stop = new AtomicBoolean(false); // Version 1
public boolean isStopped() {
return stop.get(); // Version 1
return Thread.currentThread().isInterrupted(); // Version 2
}
public void shutdown() {
logger.debug("Stopping my runnable");
stop.set(true); // Version 1
Thread.currentThread().interrupt(); // Version 2
}
@Override
public void run() {
try{
while(!isStopped()) {
// Do things
}
logger.debug("Exiting from infinite loop");
} catch(Exception e){
logger.error("Exception! " + e.getMessage());
} finally {
logger.debug("Entering in finally part");
// Flush buffer, commit to database, ... close stuff
}
}
}
但关断功能的输出始终是相同的:
Shut down everything.
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1260)
at java.lang.Thread.join(Thread.java:1334)
at com.my.packageName.MainClass.shutDown(MainClass.java:374)
Shutdown other stuff
Shutdown logger
Done
如果我删除的连接()函数,异常消失,但输出仍然相同。
编辑:我刚刚注意到,如果我评论的线myRunnable.shutdown();
和我去与myThread.join();
线,我仍然得到例外,即使我不停止该线程。这是为什么?是否因为Tread和Runnable是两个单独的东西?如果是这样,那我该如何停止Runnable并等待其完成?
好了,现在我明白了。谢谢!我中断了调用者的线程而不是被调用者的线程。现在,我没有得到例外,但我仍然无法在日志中看到“退出无限循环”字符串,也没有收到“关闭其他东西”。它似乎不再从无限循环退出。函数isStopped()是否正确?哪个线程正在检查,调用者还是被调用者?我怎样才能从可运行的程序中检查被调用者? – ocramot
PS:我仍然无法摆脱版本2的无限循环,这将是最正确的版本;但不知何故版本1正在按照预期工作,并进行更正。最好检查我的代码。谢谢!我仍然不明白为什么会发生这种情况,但我接受了你的答案。 – ocramot
好的,为了记录,我发现为什么版本2不起作用。 Symply说,我有一个'尝试{Thread.sleep(time);} catch(InterruptedException e){...}'块在我的无限循环中。所以线程在睡眠中被中断,异常被抛出并被捕获,并且无限循环继续运行。 – ocramot