2015-10-07 81 views
1

當我使用ScheduledExecutorService(或ExecutorService)並提交Runnable時,我的關閉鉤子永遠不會被調用。當然,這個程序掛起:ScheduledExecutorService和Shutdown Hook

public class App { 
    static ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); 

    static { 
    Runtime.getRuntime().addShutdownHook(new Thread() { 
     public void run() { 
     exec.shutdownNow(); 
     } 
    }); 
    } 

    public static void main(String[] args) { 
    exec.schedule(new Runnable() { 
     @Override 
     public void run() { 
     } 
    }, 10, TimeUnit.SECONDS); 
    } 
} 

由於執行的線程不是一個守護進程,我預計要調用的關閉掛鉤,但事實並非如此。任何想法爲什麼?

+0

爲什麼你認爲關閉掛鉤會被調用? –

+0

_I不會期望關閉鉤子被調用,但它不是._是不是你期望的? –

+0

@SotiriosDelimanolis我編輯他的問題,因爲我認爲這是一個錯字。 –

回答

1

在你絕對需要關閉任務後,執行事件已運行就可以實現這樣的事情:

static { 
    Runtime.getRuntime().addShutdownHook(new Thread() { 
     public void run() { 
      Logger.getGlobal().info("destroying"); 
      exec.shutdownNow(); 
     } 
    }); 
} 

public static void main(String[] args) throws Exception { 
    Future f = exec.schedule(new Runnable() { 
     @Override 
     public void run() { 
      Logger.getGlobal().info("thread run"); 

     } 
    }, 10, TimeUnit.SECONDS); 
    while (!f.isDone()) { 
     Logger.getGlobal().info("waiting for task to finish"); 
     Thread.sleep(1000); 
    } 
    Runtime.getRuntime().exit(0); 
} 
2

Runtime#addShutdownHook(Thread)的Javadoc:

Java虛擬機在響應關閉以2種 事件:

  • 程序正常退出,當最後一個非守護線程退出或退出時(等效地,System.exit)方法被調用
  • 虛擬機終止以響應用戶中斷,例如鍵入^ C,o r系統級事件,如用戶註銷或系統關閉。 *

正如你自己說的,通過​​返回在Executor線程是不是守護線程。所以它們必須在你的關閉鉤子被調用之前退出。

你正在做事情倒退。您需要從程序執行的其他部分關閉Executor,而不是關閉鉤子。關機掛鉤將在Executor終止後運行。

*假設您沒有嘗試向您的java進程發送用戶中斷。