java 线程的几种状态(转载)
java thread的運(yùn)行周期中, 有幾種狀態(tài), 在 java.lang.Thread.State 中有詳細(xì)定義和說(shuō)明:
NEW 狀態(tài)是指線程剛創(chuàng)建, 尚未啟動(dòng)
RUNNABLE 狀態(tài)是線程正在正常運(yùn)行中, 當(dāng)然可能會(huì)有某種耗時(shí)計(jì)算/IO等待的操作/CPU時(shí)間片切換等, 這個(gè)狀態(tài)下發(fā)生的等待一般是其他系統(tǒng)資源, 而不是鎖, Sleep等
BLOCKED? 這個(gè)狀態(tài)下, 是在多個(gè)線程有同步操作的場(chǎng)景, 比如正在等待另一個(gè)線程的synchronized 塊的執(zhí)行釋放, 或者可重入的 synchronized塊里別人調(diào)用wait() 方法, 也就是這里是線程在等待進(jìn)入臨界區(qū)WAITING? 這個(gè)狀態(tài)下是指線程擁有了某個(gè)鎖之后, 調(diào)用了他的wait方法, 等待其他線程/鎖擁有者調(diào)用 notify / notifyAll 一遍該線程可以繼續(xù)下一步操作, 這里要區(qū)分 BLOCKED 和 WATING 的區(qū)別, 一個(gè)是在臨界點(diǎn)外面等待進(jìn)入, 一個(gè)是在理解點(diǎn)里面wait等待別人notify, 線程調(diào)用了join方法 join了另外的線程的時(shí)候, 也會(huì)進(jìn)入WAITING狀態(tài), 等待被他join的線程執(zhí)行結(jié)束
TIMED_WAITING? 這個(gè)狀態(tài)就是有限的(時(shí)間限制)的WAITING, 一般出現(xiàn)在調(diào)用wait(long), join(long)等情況下, 另外一個(gè)線程sleep后, 也會(huì)進(jìn)入TIMED_WAITING狀態(tài)
TERMINATED 這個(gè)狀態(tài)下表示 該線程的run方法已經(jīng)執(zhí)行完畢了, 基本上就等于死亡了(當(dāng)時(shí)如果線程被持久持有, 可能不會(huì)被回收)
下面談?wù)勅绾巫尵€程進(jìn)入以上幾種狀態(tài):
1. NEW, 這個(gè)最簡(jiǎn)單了, ? ? ? ? ?static?void?NEW()?{ ??????????Thread?t =?new?Thread?(); ?????????System.?out.println(t.getState()); ????} ? 輸出NEW ? 2. RUNNABLE, 也簡(jiǎn)單, 讓一個(gè)thread start, 同時(shí)代碼里面不要sleep或者wait等 ? ? ?private?static?void?RUNNABLE() { ?????????Thread t =?new?Thread(){ ????????????? ??????????????public?void?run(){ ??????????????????for(int?i=0; i<Integer.MAX_VALUE; i++){ ??????????????????????System.?out.println(i); ?????????????????} ?????????????} ????????????? ?????????}; ????????? ?????????t.start(); ????} ? ? ? 3. BLOCKED, 這個(gè)就必須至少兩個(gè)線程以上, 然后互相等待synchronized 塊 ? ? ?????? ? ? ?private?static?void?BLOCKED() { ????????? ??????????final?Object lock =?new?Object(); ????????? ?????????Runnable run =?new?Runnable() { ????????????? ??????????????@Override ??????????????public?void?run() { ??????????????????for(int?i=0; i<Integer.MAX_VALUE; i++){ ?????????????????????? ???????????????????????synchronized?(lock) { ??????????????????????????System.?out.println(i); ??????????????????????} ?????????????????????? ?????????????????} ?????????????} ?????????}; ????????? ?????????Thread t1 =?new?Thread(run); ?????????t1.setName(?“t1”); ?????????Thread t2 =?new?Thread(run); ?????????t2.setName(?“t2”); ????????? ?????????t1.start(); ?????????t2.start(); ????????? ????} ? 這時(shí)候, 一個(gè)在RUNNABLE, 另一個(gè)就會(huì)在BLOCKED (等待另一個(gè)線程的 System.out.println.. 這是個(gè)IO操作, 屬于系統(tǒng)資源, 不會(huì)造成WAITING等) ? 4. WAITING, 這個(gè)需要用到生產(chǎn)者消費(fèi)者模型, 當(dāng)生產(chǎn)者生產(chǎn)過(guò)慢的時(shí)候, 消費(fèi)者就會(huì)等待生產(chǎn)者的下一次notify ? ? ? ?private?static?void?WAITING() { ? ??????????final?Object lock =?new?Object(); ?????????Thread t1 =?new?Thread(){ ??????????????@Override ??????????????public?void?run() { ????????????????? ??????????????????int?i = 0; ????????????????? ??????????????????while(true?){ ???????????????????????synchronized?(lock) { ???????????????????????????try?{ ???????????????????????????????lock.wait(); ??????????????????????????}?catch?(InterruptedException e) { ??????????????????????????} ??????????????????????????System.?out.println(i++); ??????????????????????} ?????????????????} ?????????????} ?????????}; ????????? ?????????Thread t2 =?new?Thread(){ ??????????????@Override ??????????????public?void?run() { ????????????????? ??????????????????while(true?){ ???????????????????????synchronized?(lock) { ???????????????????????????for(int?i = 0; i< 10000000; i++){ ??????????????????????????????System.?out.println(i); ??????????????????????????} ??????????????????????????lock.notifyAll(); ??????????????????????} ?????????????????????? ?????????????????} ?????????????} ?????????}; ????????? ?????????t1.setName(?“^^t1^^”); ?????????t2.setName(?“^^t2^^”); ????????? ?????????t1.start(); ?????????t2.start(); ????} ? ? ? 5. TIMED_WAITING, 這個(gè)僅需要在4的基礎(chǔ)上, 在wait方法加上一個(gè)時(shí)間參數(shù)進(jìn)行限制就OK了. ? 把4中的synchronized 塊改成如下就可以了. ? synchronized?(lock) { ???try?{ ? ? ? lock.wait(60 * 1000L); ? ?}?catch?(InterruptedException e) { ? ?} ? ?System.?out?.println(i++); ?} ? ? 另外看stack的輸出, ?他叫 TIMED_WAITING(on ?object monitor) , 說(shuō)明括號(hào)后面還有其他的情況, 比如sleep, 我們直接把t2的for循環(huán)改成sleep試試: ? synchronized?(lock) { ????????try?{ ??????????sleep(30*1000L); ????}?catch?(InterruptedException e) { ????} ????lock.notifyAll(); } ? ? 看到了吧, t2的state是 TIMED_WAITING( sleeping), ?而t1依然是on object monitor , 因?yàn)閠1還是wait在等待t2 notify, 而t2是自己sleep ? 另外, join操作也是進(jìn)入 on object monitor ? 6. TERMINATED, 這個(gè)狀態(tài)只要線程結(jié)束了run方法, 就會(huì)進(jìn)入了… ? ? ??private?static?void?TERMINATED() { ?????????Thread t1 =?new?Thread(); ?????????t1.start(); ?????????System.?out.println(t1.getState()); ??????????try?{ ?????????????Thread.?sleep(1000L); ?????????}?catch?(InterruptedException?e) { ?????????} ?????????System.?out.println(t1.getState()); ????} 輸出:? RUNNABLE TERMINATED ? 由于線程的start方法是異步啟動(dòng)的, 所以在其執(zhí)行后立即獲取狀態(tài)有可能才剛進(jìn)入RUN方法且還未執(zhí)行完畢 ? ? 廢話了這么多, 了解線程的狀態(tài)究竟有什么用? 所以說(shuō)這是個(gè)釣魚(yú)貼么… ? 好吧, 一句話, 在找到系統(tǒng)中的潛在性能瓶頸有作用. ? 當(dāng)java系統(tǒng)運(yùn)行慢的時(shí)候, 我們想到的應(yīng)該先找到性能的瓶頸, 而jstack等工具, 通過(guò)jvm當(dāng)前的stack可以看到當(dāng)前整個(gè)vm所有線程的狀態(tài), 當(dāng)我們看到一個(gè)線程狀態(tài)經(jīng)常處于 WAITING 或者 BLOCKED的時(shí)候, 要小心了, 他可能在等待資源經(jīng)常沒(méi)有得到釋放(當(dāng)然, 線程池的調(diào)度用的也是各種隊(duì)列各種鎖, 要區(qū)分一下, 比如下圖) 這是個(gè)經(jīng)典的并發(fā)包里面的線程池, 其調(diào)度隊(duì)列用的是LinkedBlockingQueue, 執(zhí)行take的時(shí)候會(huì)block住, 等待下一個(gè)任務(wù)進(jìn)入隊(duì)列中, 然后進(jìn)入執(zhí)行, 這種理論上不是系統(tǒng)的性能瓶頸, 找瓶頸一般先找自己的代碼stack,再去排查那些開(kāi)源的組件/JDK的問(wèn)題 ? 排查問(wèn)題的幾個(gè)思路: ? 0. 如何跟蹤一個(gè)線程? 看到上面的stack輸出沒(méi)有, 第一行是內(nèi)容是 threadName priority tid nid desc 更過(guò)跟蹤tid, nid 都可以唯一找到該線程. ? 1. 發(fā)現(xiàn)有線程進(jìn)入BLOCK, 而且持續(xù)好久, 這說(shuō)明性能瓶頸存在于synchronized塊中, 因?yàn)樗恢眀lock住, 進(jìn)不去, 說(shuō)明另一個(gè)線程一直沒(méi)有處理好, 也就這個(gè)synchronized塊中處理速度比較慢, 然后再深入查看. 當(dāng)然也有可能同時(shí)block的線程太多, 排隊(duì)太久造成. ? 2. 發(fā)現(xiàn)有線程進(jìn)入WAITING, 而且持續(xù)好久, 說(shuō)明性能瓶頸存在于觸發(fā)notify的那段邏輯. 當(dāng)然還有就是同時(shí)WAITING的線程過(guò)多, 老是等不到釋放. ? 3. 線程進(jìn)入TIME_WAITING 狀態(tài)且持續(xù)好久的, 跟2的排查方式一樣. ? ? 上面的黑底白字截圖都是通過(guò)jstack打印出來(lái)的, 可以直接定位到你想知道的線程的執(zhí)行棧, 這對(duì)java性能瓶頸的分析是有極大作用的. ? NOTE: 上面所有代碼都是為了跟蹤線程的狀態(tài)而寫(xiě)的, 千萬(wàn)不要在線上應(yīng)用中這么寫(xiě)…
Posts related to java 線程的幾種狀態(tài)
轉(zhuǎn)載于:https://www.cnblogs.com/zhengah/p/4826405.html
總結(jié)
以上是生活随笔為你收集整理的java 线程的几种状态(转载)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 学习Java第一个月
- 下一篇: 连载《一个程序猿的生命周期》- 32、两