1. 程式人生 > >JAVA-初步認識-第十二章-JVM中的多線程分析

JAVA-初步認識-第十二章-JVM中的多線程分析

finalize 不定 調用函數 處理 編譯 出現 bject 自動運行 jvm

一.

我們學java程序學到現在,到底是多線程的,還是單線程的?(現實中多線程是一直存在的,我們只是才開始學習這個概念而已,沒學過不代表不存在。)

虛擬機的啟動本身就依賴了多條線程,為什麽?

舉例來看,(舉實例來研究多線程)

技術分享圖片

New了三個匿名對象,畫一個堆內存演示一下。

左邊是棧,右邊是堆。棧裏面有主函數,主函數裏有代碼。堆裏面開始創建對象,匿名對象一創建完就是垃圾了(沒有指向),現在有三個垃圾。

技術分享圖片

主函數裏面代碼有很多,它繼續在執行。

技術分享圖片

從這裏面立刻就可以得到第一點,就是我們的java虛擬機在運行的時候肯定有一條線程是在執行主函數的。這是必須的,沒有這個線程,主函數根本無法運行。有人說,不是虛擬機調用主函數的麽?再怎麽調用,都要依賴線程來執行,因為只有線程才能執行代碼。其中有一條線程是負責主線程執行的。(調用函數完全是編程語言,線程則有點涉及硬件了)

在堆內存中出現了垃圾,需要回收。如果出現了回收的動作,有人說主線程來執行垃圾的回收,那也就意味著程序運行到一半停止了,主函數去執行垃圾的回收了。這不對,垃圾的回收我們是看不著的。

主線程執行的過程中,垃圾回收器會不定時地來回收這個垃圾,意味著有人在做這個回收的動作,這就代表著有兩個線程。其實不止兩個,有很多線程,沒有必要一一介紹。虛擬機底層它有開啟多線程需要去做的任務,只不過這條任務我們可以分析地出來(這條任務就是主函數運行,垃圾回收)。→虛擬機在程序運行過程中貌似很重要。

本身虛擬機的啟動,線程就不止一個。專門處理垃圾回收的線程我們稱之為垃圾回收線程,在主函數中執行代碼的線程稱之為主線程。

技術分享圖片

任何一個線程啟動後,都有它們自己的任務。

垃圾回收線程的內容,或者說任務代碼都在垃圾回收器內部定義呢,我們不用管,它本身是在內部自動運行的,不需要我們去執行它。

對於垃圾回收裝置,我們做一個簡單地演示,是怎麽回收的。這是底層內部完成的。

怎麽演示呢?試想一下,堆內存中會產生很多對象,每個對象都具備著被回收的可能。對象怎麽被回收的,只有對象自己最清楚。對象創建完以後,每個對象都有自己的執行特點,它怎麽被回收,它自己最清楚,每個對象都具備著被回收的方法。寫對象的時候,調用這個方法麽?沒有,每個對象都具備的方法在object類中。

技術分享圖片

這個方法就是finalize,如果不需要配置系統資源或執行其他清除,就不用重寫finalize方法。(finalize就是回收)

現在驗證一下,finalize方法到底是怎麽一回事。

其實根本不用復寫,因為它不需要做這個事情,它裏面產生對象並沒有做太多封裝數據,直接把內存清除掉就完事了,跟我們棧內存釋放原理,清除內存空間把數據抹去,存儲其它數據就完事了。只有涉及到系統資源的,才會去進行finalize的定義以及關閉系統資源。

技術分享圖片

技術分享圖片

DOS的運行結果沒有demo ok。

我們知道這三個匿名對象是變成垃圾了,但是它們立刻就被回收了嗎?不一定,它們在不定時的時間裏回收。

技術分享圖片

什麽是垃圾回收器呢?就是垃圾回收的那個程序。這程序在做垃圾回收的動作,這程序在被單獨的一個線程負責執行。如果找到這個垃圾回收器。

技術分享圖片

技術分享圖片

系統類裏面有一個gc方法。這個方法可以運行垃圾回收器。通過這個系統類的靜態方法來運行垃圾回收器。

技術分享圖片

截圖中的gc不是立刻讓垃圾回收器啟動,是在告訴垃圾回收器你要啟動,至於怎麽啟動它說了算的。

技術分享圖片

為什麽hello world先輸出了?按理說,垃圾回收器啟動了,它會回收兩個垃圾吧,一收的時候就調用了這個對象的finalize方法。說了嘛,垃圾回收器會調用finalize方法,一打印說明有垃圾被回收掉了。

(gc方法啟動垃圾回收器,垃圾回收器啟用finalize方法,真正起到回收作用的是finalize)

為什麽hello world會在demo ok前面打印呢?因為這是兩個線程完成的。主線程調用到gc的時候,這個時候就在告訴垃圾回收器。垃圾回收器就會在不定時啟動機器,同時主線程繼續往下運行,而垃圾回收線程獨立於主線程操作。在主線程打印了hello world後,垃圾處理

器才處理了兩個垃圾對象。

修改一下程序,再看結果

技術分享圖片

技術分享圖片

編譯運行多次後,出現了兩種DOS結果。這裏面兩個概念,一個是slime,一個是優先級。現在先不談技術,先討論一下現象。

除了上面兩種情況外,還有可能出現demo ok先出來的情況。

技術分享圖片

上圖的這種情況是,垃圾回收器剛回收了一個,虛擬機就結束了。虛擬機結束的話,它會強制地結束它所在的進程(就是內存區域),就是java.exe程序被結束進程了,內存就都被清除了。因此,還沒等調用finalize就結束了。(整個虛擬機都結束了,更何況裏面的垃圾回收線程)

上面的例子驗證出來,至少有兩個線程。

其實還有一個線程,主線程執行完以後,這些代碼都結束了。線程的任務只要一結束,線程就結束了,也就意味著主線程結束了。有人說主線程都結束了,虛擬機還搞什麽?hello world都打印完了,虛擬機應該退出。告訴你,僅僅是主線程結束了,虛擬機中的其他線程還在執行,虛擬機還沒結束呢。

總結:虛擬機當中所涉及的多線程內容。

JAVA-初步認識-第十二章-JVM中的多線程分析