swing程序的關閉機制--看好你的swing.Timer,別讓它成為程序不能退出的原凶


  java中常見的Timer有兩個,一個是javax.swing.Timer,另一個是java.utl.Timer,兩者的功能大同小異,最主要的差別在於swing.Timer的任務是放到EDT線程中執行的,可以很方便地進行swing的UI操作,另外swing.Timer是一個守護線程,utl.Timer則是可以設置是否為守護線程。

  JVM中有這樣一個規定,如果非守護線程都退出了,那么JVM會關閉,不管是否還有守護線程在運行。

  swing程序的關閉機制:在swing程序中,EDT線程負責處理事件,它是一個非守護線程;另外有一個名為AWT-Shutdown的非守護線程,負責在所有窗口都關閉后,關閉EDT線程,然后自己退出,所以正常情況下,窗口都關閉時,程序是會自動退出的(不是調用System.exit)。

  前不久在項目中碰到個問題,我使用了一個循環執行的Timer后(以下均指javax.swing.Timer),窗口全關閉后程序也不退出了(窗口全關閉后,如果再沒有非守護線程,虛擬機應該是會自動退出的),后來我把timer的周期改為了1000+毫秒,程序就能退出了,小於1000就無法退出。之后經過調試跟蹤,了解了swing的關閉機制,而且注意到,在窗口都關閉時,AWT-Shutdown它並不是立即關閉EDT線程,而是mainLock.wait1000毫秒,然后再次檢查關閉條件(還會檢查EDT中是否有任務正在執行),如果不符合,就繼續尋找關閉的時機,循環此過程,所以,如果timer的間隔小於1000,主意味着,AWT-Shutdown在waait的1000毫秒中,又有新的任務被放到EDT任務隊列中,當AWT-Shutdown醒來時,關閉條件又不符合了,所以,如果你的timer間隔小於1000,將造成AWT-Shutdown不能關閉EDT,程序無法退出,說到這里,可能大家也明白了,並不只是timer,使用SwingUtilities.invokeAndWait、invokeLater、SwingWorker等,都會有此問題。

  有興趣的朋友可以閱讀下AWTAutoShutdown的源碼,那些細節挺有意思的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM