這篇文章主要講解了“thread dump線程狀態(tài)以及線程的定義是什么”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“thread dump線程狀態(tài)以及線程的定義是什么”吧!
紅橋網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),紅橋網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為紅橋成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的紅橋做網(wǎng)站的公司定做!
周末看到一個用jstack查看死鎖的例子。昨天晚上總結(jié)了一下jstack(查看線程)、jmap(查看內(nèi)存)和jstat(性能分析)命令。供大家參考
1.1 jstack能得到運行java程序的java stack和native stack的信息。可以輕松得知當前線程的運行情況。如下圖所示
注:這個和thread dump是同樣的結(jié)果。但是thread dump是用kill -3 pid命令,還是服務(wù)器上面少用kill為妙
1.2 命名行格式
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
最常用的還是jstack pid
1.3 在thread dump中,要留意下面幾種狀態(tài)
死鎖,Deadlock(重點關(guān)注)
等待資源,Waiting on condition(重點關(guān)注)
? 等待獲取監(jiān)視器,Waiting on monitor entry(重點關(guān)注)
阻塞,Blocked(重點關(guān)注)
? 執(zhí)行中,Runnable
? 暫停,Suspended
? 對象等待中,Object.wait() 或 TIMED_WAITING
? 停止,Parked
下面有詳細的例子講這種分析,大家參考原著
http://www.cnblogs.com/zhengyun_ustc/archive/2013/01/06/dumpanalysis.html
1.4 在thread dump中,有幾種線程的定義如下
線程名稱 所屬 解釋說明
Attach Listener JVM Attach Listener 線程是負責接收到外部的命令,而對該命令進行執(zhí)行的并且吧結(jié)果返回給發(fā)送者。通常我們會用一些命令去要求jvm給我們一些反饋信息,如:java -version、jmap、jstack等等。 如果該線程在jvm啟動的時候沒有初始化,那么,則會在用戶第一次執(zhí)行jvm命令時,得到啟動。
Signal Dispatcher JVM 前面我們提到第一個Attach Listener線程的職責是接收外部jvm命令,當命令接收成功后,會交給signal dispather 線程去進行分發(fā)到各個不同的模塊處理命令,并且返回處理結(jié)果。 signal dispather線程也是在第一次接收外部jvm命令時,進行初始化工作。
CompilerThread0 JVM 用來調(diào)用JITing,實時編譯裝卸class 。 通常,jvm會啟動多個線程來處理這部分工作,線程名稱后面的數(shù)字也會累加,例如:CompilerThread1
Concurrent Mark-Sweep GC Thread JVM 并發(fā)標記清除垃圾回收器(就是通常所說的CMS GC)線程, 該線程主要針對于老年代垃圾回收。ps:啟用該垃圾回收器,需要在jvm啟動參數(shù)中加上: -XX:+UseConcMarkSweepGC
DestroyJavaVM JVM 執(zhí)行main()的線程在main執(zhí)行完后調(diào)用JNI中的 jni_DestroyJavaVM() 方法喚起DestroyJavaVM 線程。 JVM在 Jboss 服務(wù)器啟動之后,就會喚起DestroyJavaVM線程,處于等待狀態(tài),等待其它線程(java線程和native線程)退出時通知它卸載JVM。線程退出時,都會判斷自己當前是否是整個JVM中最后一個非deamon線程,如果是,則通知DestroyJavaVM 線程卸載JVM。
ps:
擴展一下:
1.如果線程退出時判斷自己不為最后一個非deamon線程,那么調(diào)用thread->exit(false) ,并在其中拋出thread_end事件,jvm不退出。
2.如果線程退出時判斷自己為最后一個非deamon線程,那么調(diào)用before_exit() 方法,拋出兩個事件: 事件1:thread_end 線程結(jié)束事件、事件2:VM的death事件。
然后調(diào)用thread->exit(true) 方法,接下來把線程從active list卸下,刪除線程等等一系列工作執(zhí)行完成后,則通知正在等待的DestroyJavaVM 線程執(zhí)行卸載JVM操作。
ContainerBackgroundProcessor 線程 JBOSS 它是一個守護線程, 在jboss服務(wù)器在啟動的時候就初始化了,主要工作是定期去檢查有沒有Session過期.過期則清除.
參考:http://liudeh-009.iteye.com/blog/1584876
Dispatcher-Thread-3 線程 Log4j Log4j具有異步打印日志的功能,需要異步打印日志的Appender都需要注冊到 AsyncAppender對象里面去,由AsyncAppender進行監(jiān)聽,決定何時觸發(fā)日志打印操作。 AsyncAppender如果監(jiān)聽到它管轄范圍內(nèi)的Appender有打印日志的操作,則給這個Appender生成一個相應(yīng)的event,并將該event保存在一個buffuer區(qū)域內(nèi)。 Dispatcher-Thread-3線程負責判斷這個event緩存區(qū)是否已經(jīng)滿了,如果已經(jīng)滿了,則將緩存區(qū)內(nèi)的所有event分發(fā)到Appender容器里面去,那些注冊上來的Appender收到自己的event后,則開始處理自己的日志打印工作。 Dispatcher-Thread-3線程是一個守護線程。
Finalizer線程 JVM 這個線程也是在main線程之后創(chuàng)建的,其優(yōu)先級為10,主要用于在垃圾收集前,調(diào)用對象的finalize()方法;關(guān)于Finalizer線程的幾點:
1) 只有當開始一輪垃圾收集時,才會開始調(diào)用finalize()方法;因此并不是所有對象的finalize()方法都會被執(zhí)行;
2) 該線程也是daemon線程,因此如果虛擬機中沒有其他非daemon線程,不管該線程有沒有執(zhí)行完finalize()方法,JVM也會退出;
3) JVM在垃圾收集時會將失去引用的對象包裝成Finalizer對象(Reference的實現(xiàn)),并放入ReferenceQueue,由Finalizer線程來處理;最后將該Finalizer對象的引用置為null,由垃圾收集器來回收;
4) JVM為什么要單獨用一個線程來執(zhí)行finalize()方法呢?如果JVM的垃圾收集線程自己來做,很有可能由于在finalize()方法中誤操作導致GC線程停止或不可控,這對GC線程來說是一種災(zāi)難;
Gang worker#0 JVM JVM 用于做新生代垃圾回收(monir gc)的一個線程。#號后面是線程編號,例如:Gang worker#1
GC Daemon JVM GC Daemon 線程是JVM為RMI提供遠程分布式GC使用的,GC Daemon線程里面會主動調(diào)用System.gc()方法,對服務(wù)器進行Full GC。 其初衷是當 RMI 服務(wù)器返回一個對象到其客戶機(遠程方法的調(diào)用方)時,其跟蹤遠程對象在客戶機中的使用。當再沒有更多的對客戶機上遠程對象的引用時,或者如果引用的“租借”過期并且沒有更新,服務(wù)器將垃圾回收遠程對象。
不過,我們現(xiàn)在jvm啟動參數(shù)都加上了-XX:+DisableExplicitGC配置,所以,這個線程只有打醬油的份了。
IdleRemover JBOSS Jboss連接池有一個最小值, 該線程每過一段時間都會被Jboss喚起,用于檢查和銷毀連接池中空閑和無效的連接,直到剩余的連接數(shù)小于等于它的最小值。
Java2D Disposer JVM 這個線程主要服務(wù)于awt的各個組件。 說起該線程的主要工作職責前,需要先介紹一下Disposer類是干嘛的。 Disposer提供一個addRecord方法。 如果你想在一個對象被銷毀前再做一些善后工作,那么,你可以調(diào)用Disposer#addRecord方法,將這個對象和一個自定義的DisposerRecord接口實現(xiàn)類,一起傳入進去,進行注冊。
Disposer類會喚起“Java2D Disposer”線程,該線程會掃描已注冊的這些對象是否要被回收了,如果是,則調(diào)用該對象對應(yīng)的DisposerRecord實現(xiàn)類里面的dispose方法。
Disposer實際上不限于在awt應(yīng)用場景,只是awt里面的很多組件需要訪問很多操作系統(tǒng)資源,所以,這些組件在被回收時,需要先釋放這些資源。
InsttoolCacheScheduler_
QuartzSchedulerThread Quartz InsttoolCacheScheduler_QuartzSchedulerThread是Quartz的主線程,它主要負責實時的獲取下一個時間點要觸發(fā)的觸發(fā)器,然后執(zhí)行觸發(fā)器相關(guān)聯(lián)的作業(yè) 。
原理大致如下:
Spring和Quartz結(jié)合使用的場景下,Spring IOC容器初始化時會創(chuàng)建并初始化Quartz線程池(TreadPool),并啟動它。剛啟動時線程池中每個線程都處于等待狀態(tài),等待外界給他分配Runnable(持有作業(yè)對象的線程)。
繼而接著初始化并啟動Quartz的主線程(InsttoolCacheScheduler_QuartzSchedulerThread),該線程自啟動后就會處于等待狀態(tài)。等待外界給出工作信號之后,該主線程的run方法才實質(zhì)上開始工作。run中會獲取JobStore中下一次要觸發(fā)的作業(yè),拿到之后會一直等待到該作業(yè)的真正觸發(fā)時間,然后將該作業(yè)包裝成一個JobRunShell對象(該對象實現(xiàn)了Runnable接口,其實看是上面TreadPool中等待外界分配給他的Runnable),然后將剛創(chuàng)建的JobRunShell交給線程池,由線程池負責執(zhí)行作業(yè)。
線程池收到Runnable后,從線程池一個線程啟動Runnable,反射調(diào)用JobRunShell中的run方法,run方法執(zhí)行完成之后, TreadPool將該線程回收至空閑線程中。
InsttoolCacheScheduler_Worker-2 Quartz InsttoolCacheScheduler_Worker-2線程就是ThreadPool線程的一個簡單實現(xiàn),它主要負責分配線程資源去執(zhí)行
InsttoolCacheScheduler_QuartzSchedulerThread線程交給它的調(diào)度任務(wù)(也就是JobRunShell)。
JBossLifeThread Jboss Jboss主線程啟動成功,應(yīng)用程序部署完畢之后將JBossLifeThread線程實例化并且start,JBossLifeThread線程啟動成功之后就處于等待狀態(tài),以保持Jboss Java進程處于存活中。 所得比較通俗一點,就是Jboss啟動流程執(zhí)行完畢之后,為什么沒有結(jié)束? 就是因為有這個線程hold主了它。 牛b吧~~
JBoss System Threads(1)-1 Jboss 該線程是一個socket服務(wù),默認端口號為: 1099。 主要用于接收外部naming service(Jboss JNDI)請求。
JCA PoolFiller Jboss 該線程主要為JBoss內(nèi)部提供連接池的托管。 簡單介紹一下工作原理 :
Jboss內(nèi)部凡是有遠程連接需求的類,都需要實現(xiàn)ManagedConnectionFactory接口,例如需要做JDBC連接的
XAManagedConnectionFactory對象,就實現(xiàn)了該接口。然后將XAManagedConnectionFactory對象,還有其它信息一起包裝到InternalManagedConnectionPool對象里面,接著將InternalManagedConnectionPool交給PoolFiller對象里面的列隊進行管理。 JCA PoolFiller線程會定期判斷列隊內(nèi)是否有需要創(chuàng)建和管理的InternalManagedConnectionPool對象,如果有的話,則調(diào)用該對象的fillToMin方法, 觸發(fā)它去創(chuàng)建相應(yīng)的遠程連接,并且將這個連接維護到它相應(yīng)的連接池里面去。
JDWP Event Helper Thread JVM
JDWP是通訊交互協(xié)議,它定義了調(diào)試器和被調(diào)試程序之間傳遞信息的格式。它詳細完整地定義了請求命令、回應(yīng)數(shù)據(jù)和錯誤代碼,保證了前端和后端的JVMTI和JDI的通信通暢。 該線程主要負責將JDI事件映射成JVMTI信號,以達到調(diào)試過程中操作JVM的目的。
JDWP Transport Listener: dt_socket JVM 該線程是一個Java Debugger的監(jiān)聽器線程,負責受理客戶端的debug請求。 通常我們習慣將它的監(jiān)聽端口設(shè)置為8787。
Low Memory Detector JVM 這個線程是負責對可使用內(nèi)存進行檢測,如果發(fā)現(xiàn)可用內(nèi)存低,分配新的內(nèi)存空間。
process reaper JVM 該線程負責去執(zhí)行一個 OS 命令行的操作。
Reference Handler JVM JVM在創(chuàng)建main線程后就創(chuàng)建Reference Handler線程,其優(yōu)先級最高,為10,它主要用于處理引用對象本身(軟引用、弱引用、虛引用)的垃圾回收問題 。
Surrogate Locker Thread (CMS) JVM 這個線程主要用于配合CMS垃圾回收器使用,它是一個守護線程,其主要負責處理GC過程中,Java層的Reference(指軟引用、弱引用等等)與jvm 內(nèi)部層面的對象狀態(tài)同步。 這里對它們的實現(xiàn)稍微做一下介紹:這里拿 WeakHashMap做例子,將一些關(guān)鍵點先列出來(我們后面會將這些關(guān)鍵點全部串起來):
1. 我們知道HashMap用Entry[]數(shù)組來存儲數(shù)據(jù)的,WeakHashMap也不例外, 內(nèi)部有一個Entry[]數(shù)組。
2. WeakHashMap的Entry比較特殊,它的繼承體系結(jié)構(gòu)為Entry->WeakReference->Reference 。
3. Reference 里面有一個全局鎖對象:Lock,它也被稱為pending_lock. 注意:它是靜態(tài)對象。
4. Reference 里面有一個靜態(tài)變量:pending。
5. Reference 里面有一個靜態(tài)內(nèi)部類:ReferenceHandler的線程,它在static塊里面被初始化并且啟動,啟動完成后處于wait狀態(tài),它在一個Lock同步鎖模塊中等待。
6. 另外,WeakHashMap里面還實例化了一個ReferenceQueue列隊,這個列隊的作用,后面會提到。
7. 上面關(guān)鍵點就介紹完畢了,下面我們把他們串起來。
假設(shè),WeakHashMap對象里面已經(jīng)保存了很多對象的引用。 JVM 在進行CMS GC的時候,會創(chuàng)建一個ConcurrentMarkSweepThread(簡稱CMST)線程去進行GC,ConcurrentMarkSweepThread線程被創(chuàng)建的同時會創(chuàng)建一個SurrogateLockerThread(簡稱SLT)線程并且啟動它,SLT啟動之后,處于等待階段。CMST開始GC時,會發(fā)一個消息給SLT讓它去獲取Java層Reference對象的全局鎖:Lock。 直到CMS GC完畢之后,JVM 會將WeakHashMap中所有被回收的對象所屬的WeakReference容器對象放入到Reference 的pending屬性當中(每次GC完畢之后,pending屬性基本上都不會為null了),然后通知SLT釋放并且notify全局鎖:Lock。此時激活了ReferenceHandler線程的run方法,使其脫離wait狀態(tài),開始工作了。ReferenceHandler這個線程會將pending中的所有WeakReference對象都移動到它們各自的列隊當中,比如當前這個WeakReference屬于某個WeakHashMap對象,那么它就會被放入相應(yīng)的ReferenceQueue列隊里面(該列隊是鏈表結(jié)構(gòu))。 當我們下次從WeakHashMap對象里面get、put數(shù)據(jù)或者調(diào)用size方法的時候,WeakHashMap就會將ReferenceQueue列隊中的WeakReference依依poll出來去和Entry[]數(shù)據(jù)做比較,如果發(fā)現(xiàn)相同的,則說明這個Entry所保存的對象已經(jīng)被GC掉了,那么將Entry[]內(nèi)的Entry對象剔除掉。
taskObjectTimerFactory JVM 顧名思義,該線程就是用來執(zhí)行任務(wù)的。 當我們把一個認為交給Timer對象,并且告訴它執(zhí)行時間,周期時間后,Timer就會將該任務(wù)放入任務(wù)列隊,并且通知taskObjectTimerFactory線程去處理任務(wù),taskObjectTimerFactory線程會將狀態(tài)為取消的任務(wù)從任務(wù)列隊中移除,如果任務(wù)是非重復執(zhí)行類型的,則在執(zhí)行完該任務(wù)后,將它從任務(wù)列隊中移除,如果該任務(wù)是需要重復執(zhí)行的,則計算出它下一次執(zhí)行的時間點。
VM Periodic Task Thread JVM 該線程是JVM周期性任務(wù)調(diào)度的線程,它由WatcherThread創(chuàng)建,是一個單例對象。 該線程在JVM內(nèi)使用得比較頻繁,比如:定期的內(nèi)存監(jiān)控、JVM運行狀況監(jiān)控,還有我們經(jīng)常需要去執(zhí)行一些jstat 這類命令查看gc的情況,如下:
jstat -gcutil 23483 250 7 這個命令告訴jvm在控制臺打印PID為:23483的gc情況,間隔250毫秒打印一次,一共打印7次。
VM Thread JVM 這個線程就比較牛b了,是jvm里面的線程母體,根據(jù)hotspot源碼(vmThread.hpp)里面的注釋,它是一個單例的對象(最原始的線程)會產(chǎn)生或觸發(fā)所有其他的線程,這個單個的VM線程是會被其他線程所使用來做一些VM操作(如,清掃垃圾等)。
在 VMThread 的結(jié)構(gòu)體里有一個VMOperationQueue列隊,所有的VM線程操作(vm_operation)都會被保存到這個列隊當中,VMThread 本身就是一個線程,它的線程負責執(zhí)行一個自輪詢的loop函數(shù)(具體可以參考:VMThread.cpp里面的void VMThread::loop()) ,該loop函數(shù)從VMOperationQueue列隊中按照優(yōu)先級取出當前需要執(zhí)行的操作對象(VM_Operation),并且調(diào)用VM_Operation->evaluate函數(shù)去執(zhí)行該操作類型本身的業(yè)務(wù)邏輯。
ps:VM操作類型被定義在vm_operations.hpp文件內(nèi),列舉幾個:ThreadStop、ThreadDump、PrintThreads、GenCollectFull、GenCollectFullConcurrent、CMS_Initial_Mark、CMS_Final_Remark….. 有興趣的同學,可以自己去查看源文件。
(搬運自 http://blog.csdn.net/a43350860/article/details/8134234 感謝原著作者)
2.Jmap
2.1 得到運行java程序的內(nèi)存分配的詳細情況。例如實例個數(shù),大小等
2.2 命名行格式
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
-dump:[live,]format=b,file=<filename> 使用hprof二進制形式,輸出jvm的heap內(nèi)容到文件=. live子選項是可選的,假如指定live選項,那么只輸出活的對象到文件.
-finalizerinfo 打印正等候回收的對象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情況.
-histo[:live] 打印每個class的實例數(shù)目,內(nèi)存占用,類全名信息. VM的內(nèi)部類名字開頭會加上前綴”*”. 如果live子參數(shù)加上后,只統(tǒng)計活的對象數(shù)量.
-permstat 打印classload和jvm heap長久層的信息. 包含每個classloader的名字,活潑性,地址,父classloader和加載的class數(shù)量. 另外,內(nèi)部String的數(shù)量和占用內(nèi)存數(shù)也會打印出來.
-F 強迫.在pid沒有相應(yīng)的時候使用-dump或者-histo參數(shù). 在這個模式下,live子參數(shù)無效.
-h | -help 打印輔助信息
-J 傳遞參數(shù)給jmap啟動的jvm.
2.3 使用例子
jmap -histo pid(查看實例)
下面是我用eclipse 的MemoryAnalyzer查看內(nèi)存結(jié)構(gòu)圖
例子2(連續(xù)5次)
這個工具的參數(shù)非常多,據(jù)說基本能覆蓋jprofile等收費工具的所有功能了。多用用對于系統(tǒng)調(diào)優(yōu)還是很有幫助的
注1:我們在daily用這樣命令時,都要用-F參數(shù)的。因為我們的用戶都不是啟動命令的用戶
注2:daily的這些命令好像都沒有配置到環(huán)境變量里面,這個是我在自己應(yīng)用機器里面看到的。需要去jdk目錄底下執(zhí)行。Sudo當然是必須的了
感謝各位的閱讀,以上就是“thread dump線程狀態(tài)以及線程的定義是什么”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對thread dump線程狀態(tài)以及線程的定義是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
當前標題:threaddump線程狀態(tài)以及線程的定義是什么
URL分享:http://jinyejixie.com/article28/pddgjp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、響應(yīng)式網(wǎng)站、網(wǎng)站設(shè)計公司、App開發(fā)、網(wǎng)站內(nèi)鏈、虛擬主機
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)