2015-10-22 59 views
2

我有一个类将以无限循环启动一个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并等待其完成?

回答

4

在“版本2”中,您正在中断正在调用stopParser()的线程,而不是执行run()的线程。不要致电Thread.currentThread().interrupt(),请使用myThread.interrupt()

我不知道为什么你会在“版本1”中得到InterruptedException;您必须在其他地方拨打Thread.currentThread().interrupt()。只有在检测到当前线程已被另一个线程中断但不能立即终止线程时,才应该这样做。

+0

好了,现在我明白了。谢谢!我中断了调用者的线程而不是被调用者的线程。现在,我没有得到例外,但我仍然无法在日志中看到“退出无限循环”字符串,也没有收到“关闭其他东西”。它似乎不再从无限循环退出。函数isStopped()是否正确?哪个线程正在检查,调用者还是被调用者?我怎样才能从可运行的程序中检查被调用者? – ocramot

+0

PS:我仍然无法摆脱版本2的无限循环,这将是最正确的版本;但不知何故版本1正在按照预期工作,并进行更正。最好检查我的代码。谢谢!我仍然不明白为什么会发生这种情况,但我接受了你的答案。 – ocramot

+0

好的,为了记录,我发现为什么版本2不起作用。 Symply说,我有一个'尝试{Thread.sleep(time);} catch(InterruptedException e){...}'块在我的无限循环中。所以线程在睡眠中被中断,异常被抛出并被捕获,并且无限循环继续运行。 – ocramot