亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java多線程開發系列之四:玩轉多線程(線程的控制2)

2019-11-14 23:07:00
字體:
來源:轉載
供稿:網友
java多線程開發系列之四:玩轉多線程(線程的控制2)

   在上節的線程控制(詳情點擊這里)中,我們講解了線程的等待join()、守護線程。本節我們將會把剩下的線程控制內容一并講完,主要內容有線程的睡眠、讓步、優先級、掛起和恢復、停止等。

  廢話不多說,我們直接進入正題:


3、線程睡眠 sleep()

  所有介紹多線程開發的學習案例中,基本都有用到這個方法,這個方法的意思就是睡眠(是真的,請相信我...)。好吧,如果你覺得不夠具體,可以認為是讓當前線程暫停一下,當前線程隨之進入阻塞狀態,當睡眠時間結束后,當前線程重新進入就緒狀態,開始新一輪的搶占計劃!

那么這個方法在實際開發中,有哪些用途呢?我舉個例子,很多情況下,當前線程并不需要實時的監控或者是運行,只是會定期的檢查一下某個狀態是否達標,如果符合出發條件了,那么就做某一件事情,否則繼續睡眠。比如心跳模式下,我們會派一個守護線程向服務端發送數據請求,當收到回應時,那么我們會睡眠一段時間,當再次蘇醒后,我們繼續發送這樣的請求?,F實生活中的例子,比如我們在等某個電視是否開播,可是又不想看之前的廣告,所以我們可能會等一會將電視頻道切換到要播放的位置查看一下,如果還在播放廣告,那么我們就跳到其他頻道觀看,然后定期的切換到目標頻道進行查看一下。

代碼如下:

 1     public class ThreadStudy 2     { 3         public static main(String[] arg)throws Exception 4         { 5             for(int i=0;i<=1000;i++) 6             { 7                 if(IsInternetaccess()) 8                 { 9                     Thread.sleep(1000*6);//注意這里10                 }11                 else12                 {13                     System.out.

  代碼的意思是檢查網絡是否通暢,如果通暢的話那么進入睡眠,睡眠6秒鐘后再次蘇醒進行一次檢查。通過讓線程睡眠,我們可以有效的分配資源,在閑時讓其他線程可以更快的拿到cpu資源。這里有一點需要注意的是,線程睡眠后,進入阻塞狀態(無論此時cpu是否空閑,都仍然會暫停,是強制性的),當睡眠時間結束,進入的是就緒狀態,需要再次競爭才可以搶占到cpu權限,而非睡眠結束后立即可以執行方法。所以實際間隔時間是大于等于睡眠時間的。

java Thread類提供了兩個靜態方法來暫停線程

1  static void sleep(long millis)  2 3  static void sleep(long millis,int nanos)

  millis為毫秒,nanos為微秒,與線程join()類似,由于jvm和硬件的緣故,我們也基本只用方法1。


4、線程讓步 yield()

在生活中我們都遇到過這樣的例子,在公交車、地鐵上作一名安靜的美男子(或者是女漢子),這時候進來了一位老人、孕婦等,你默默的站起來,將座位讓給了老人。自己去旁邊候著,等著新的空閑座位。或者是你默默的玩著電腦游戲,然后你媽媽大聲的喊你的全名(是的,是全名),這時候你第一反應是,我又做錯什么了,第二反應就是放下手上的鼠標,乖乖的跑到你老媽面前接受訓斥。所有的這一切都是由于事情的緊急性當前正在處理的線程被擱置起來,我們(cpu)處理當前的緊急事務。在軟件開發中,也有類似的場景,比如一條線程處理的任務過大,其他線程始終無法搶占到資源,這時候我們就要主動的進行讓步,給其他線程一個公平搶占的機會。

這里附加一份來自網絡的圖片:在我們強大的時候,我們應該給弱者一個機會??瓤?回歸正題。

下面是代碼

 1 public class TestThread extends Thead 2 { 3     public testThread(String name) 4     { 5         super(name); 6     } 7      8     public void run() 9     {10         for(int i=0;i<=1000000;ii++)11         {12             send("MsgBody");13             if(i%100==0)14             {15                 Thread.yield();//注意看這里16             }17         }18     }19     20     public static void main(String[] args) throws Exception21     {22         TestThread thread1=new TestThread("thread1");23         thread1.setPriority(Thread.MAX_PRIORITY);//注意看這里24         25         TestThread thread2=new TestThread("thread2");26         thread1.setPriority(Thread.MIN_PRIORITY);//注意看這里27         thread1.start();28         thread2.start();29     }30 }

我們啟動線程后,當線程每發送一百次消息后,我們暫停一次當前線程,使當前線程進入就緒狀態。此時CPU會重新計算一次優先級,選擇優先級較高者啟動。此處比較一下 sleep方法和yield()方法。

(1)sleep方法 暫停線程后,線程會進入阻塞狀態(即使是一瞬間),那么在這一刻cpu只會選擇已經做好就緒狀態的線程,故不會選擇當前正在睡眠的線程。(即使沒有其他可用線程)。而yield()方法會使當前線程即刻起進入就緒狀態,cpu選擇的可選線程范圍中,包含當前執行yield()方法的線程。如若沒有其他線程的優先級高于(或者等于) yield()的線程,則cpu仍會選擇原有yield()的線程重新啟動。

(2)sleep方法會拋出 InterruptedException 異常,所以調用sleep方法需要聲明或捕捉該異常(比C#處理異常而言是夠麻煩的),而yield沒有聲明拋出異常。

(3)sleep方法的移植性較好,可以對應很多平臺的底層方法,所以用sleep()的地方要多余yield()的地方;

(4)sleep 暫停線程后,線程會睡眠 一定時間,然后才會變為就緒狀態,倘若定義為sleep(0)后,則阻塞狀態的時間為0,即刻進入就緒狀態,這種用法與yield()的用法基本上是相同的:即都是讓cpu進行一次新的選擇,避免由于當前線程過度的霸占cpu,造成程序假死。

這兩個方法最大的不同點是 sleep會拋出異常需要處理,yield()不會; 而且兩者的微小區別在各個版本的jdk中也不一樣,大家看以參閱stackoverflow上的這個問題:Are Thread.sleep(0) and Thread.yield() statements equivalent?(點此進入)


5、線程的優先級設定

  線程的優先級相當于是一個機會的權重,優先級高時,獲得執行機會的可能性就越大,反之獲得執行機會的可能性就越小。(記住只是可能性越大或越?。?。

  在本節的線程讓步這一部分的代碼里我們已經用代碼展示了如何設置線程的優先級此處不做特別的代碼展示。(防盜連接:本文首發自http://www.49028c.com/jilodream/ )

Thread為我們提供了兩個方法來分別設置和獲取線程的優先級。

  

1 setPriority(int newPriority)2 getPriority()

setPriority為設置優先級,參數的取值范圍是 1~10之前。

同時還設定了三個靜態常量:Tread.MAX_PRIORITY=10;

Tread.NORM_PRIORITY=5;

Tread.MIN_PRIORITY=1;

  盡管java為線程提供了10個優先級,但是底層平臺線程的優先級往往并不為10,所以就導致了兩者不是意義對應的關系。(比如OS只有五個優先級,這樣每兩個優先級只對應一個OS的優先級)。 此時我們常常只用這三個靜態常量來設置優先級,而不是詳細的指明具體的優先級值(因為可能多個優先級對應OS的某一個優先級),造成不必要的麻煩。

  另外每個線程默認的優先級都與創建他的父進程的優先級相同,在默認情況下Main線程優先級為普通,所以上述代碼創建的新線程默認也為普通優先級。

  下面是優先級概念的重點:

  其實你設置的優先級并不能真正代表該線程的或者啟動的優先級,這只是OS啟動線程時計算優先級的一個參考指標。OS還會查看當前線程是否長時間的霸占cpu,如果是這樣的話,OS會適度的調高對其它“饑餓”線程的優先級。對于那些長期霸占cpu的線程進行強制的掛起。進行這種設置只是能在某種程度上增加該線程被執行的機會。其實那些長期霸占cpu的線程也并非單次霸占的時間長,而是被連續選中的情況非常多,造成一種長期霸占的假象。

  所以設置優先級后,線程真正執行的順序并不可以預測甚至可以說是有點混亂的。在明白了這點以后,我們在開發控制多線程,并不能完全的寄希望于通過簡單的設置優先級來安排線程的執行順序。

此處參考了兩篇文章,更多詳情請參考原文:

(1)Java多線程 -- 線程的優先級(原文鏈接)

(2)Thread.sleep(0)的意義(原文鏈接)


6、強制結束線程Stop()

有時我們會發現有些正在運行的線程,已經沒有必要繼續執行下去了,但是距離多線程結束還有一段時間,這時我們就需要強制結束多線程。java曾經提供過一個專門用于結束線程的方法Stop(),但是這個方法現在已經被廢棄掉了,并不推薦開發者使用。

  這是由于這個方法具有固有的不安全性。用Thread.stop 來結束線程,jvm會強制釋放它鎖定的所有對象。當某一時刻對象的狀態并不一致時(正在處理事務的過程中),如果強制釋放掉對象,則可能會導致很多意想不到的后果。說的具體一點就是:系統會以被鎖定資源的棧頂產生一個ThreadDeath異常。這個unchecked Exception 會默默的關閉掉相關的線程。此時對象內部的數據可能會不一致,而用戶并不會收到任何對象不一致的報警。這個不一致的后果只會在未來使用過程中才會被發現,此時已經造成了無法預料的后果。

  有些人可能會考慮通過調用Stop方法,然后再捕捉ThreadDeath的形式,避免這種形式。這種想法看似可以實現,其實由于ThreadDeath這個異常可能在任何位置拋出,需要及細致的考慮。而且即使考慮到了,在捕捉處理該異常時,系統可能又會拋出新的ThreadDeath。所以我們應該在源頭上就扼殺掉這種方式,而不是通過不斷的打補丁來修復。

那么問題來了,如果我們真的要關閉掉某個線程,應該怎么處理呢?

通過Stop方法的講解我們可以明白,在線程的外部來關閉線程往往很難處理好數據一致性、以及線程內部運行過程的問題。那么我們可以通過設定一直標志變量,然后線程定期的檢查這個變量是否為結束標識來確定是否繼續運行。

例如筆者曾經寫過一個監控計算機指標的線程。這個線程會定期的檢查緩存中的狀態變量。這個狀態緩存是外部可以設定的。當線程發現此變量已經被設定為“結束”時,則會在內部處理好剩余工作,直接運行完Run方法。


7、線程的掛起和恢復 suspend()和resume()

我們有時需要對線程進行掛起,而具體掛起的時間并不清楚,只可能在未來某個條件下,通知這個線程可以開始工作了。java為我們專門提供了這樣的兩個方法:

掛起 suspend()/恢復resume。

通過標題我們已經知道這兩個方法也同樣不被java所推薦,但是為什么會這樣呢?

suspend是直接掛起當前線程,使其進入阻塞狀態,而對他內部控制和鎖定的資源并不進行修改(這與stop方法類似,線程外部往往很難查看內部運行的狀態和控制的資源,所以也就很難處理)。這樣這個被掛起的線程所鎖定的資源就再也不能被其他資源所訪問,造成了一種假死鎖的狀態。只有當線程被恢復(resume)后,并且釋放掉手里的資源,其他線程才可以重新訪問資源,但是倘若其他線程在恢復(resume)被掛起(suspend)的線程直線,需要先訪問被鎖定的資源,此時就會形成真正的鎖定。

那么問題來了,如果我們真的要掛起某個線程,應該怎么處理呢?

  這個與stop()同理,我們可以在可能被掛起的線程內部設置一個標識,指出這個線程當前是否要被掛起,若變量指示要掛起,則使用wait()命令讓其進入等待狀態,若標識指出可以恢復線程時,則用notify()重新喚醒這個線程。(這兩個方法我會在后文的線程通信中講解)。

此處參考了兩篇文章,更多詳情請參考原文:

(1)為何不贊成使用Thread.stopsuspend和resume()(原文鏈接)

  (2)JAVA STOP方法的不安全性(原文鏈接)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
综合av色偷偷网| 国产99久久精品一区二区 夜夜躁日日躁| 国产亚洲精品va在线观看| 国产精品久久久久久搜索| 国内精品一区二区三区四区| 亚洲人成啪啪网站| 日韩高清a**址| 亚洲成人激情小说| 成人黄在线观看| 亚洲天堂免费在线| 一本色道久久综合狠狠躁篇的优点| 在线日韩日本国产亚洲| 亚洲精品久久久久久下一站| 成人看片人aa| 午夜精品蜜臀一区二区三区免费| 国产黑人绿帽在线第一区| 午夜精品在线观看| 欧美第一黄网免费网站| 丝袜美腿精品国产二区| 色悠悠久久久久| 国产欧美在线播放| 91精品在线影院| 久久影院资源站| 精品日本高清在线播放| 日韩美女视频免费看| 成人激情黄色网| 97人洗澡人人免费公开视频碰碰碰| 欧美洲成人男女午夜视频| 亚洲丝袜一区在线| 精品无码久久久久久国产| 久久精品福利视频| 亚洲成人中文字幕| 日韩亚洲欧美中文高清在线| 中文字幕日韩av电影| 精品国产91久久久| 久久精品中文字幕一区| 欧美网站在线观看| 亚洲色图第三页| 亚洲国产精品国自产拍av秋霞| 亚洲精品电影久久久| 国产精品999999| 中文字幕日韩专区| 国产精品久久久久久超碰| 91av视频导航| 亚洲欧美日韩成人| 97视频在线观看免费高清完整版在线观看| 欧美成人精品在线视频| 久久91亚洲精品中文字幕| 久久免费少妇高潮久久精品99| 夜夜嗨av一区二区三区四区| 菠萝蜜影院一区二区免费| xvideos亚洲| 国产在线观看一区二区三区| 国产在线不卡精品| 国产成人自拍视频在线观看| 欧美精品一区二区三区国产精品| 久久久国产一区二区三区| 亚洲人成网7777777国产| 色综久久综合桃花网| 欧美日韩一区二区免费在线观看| 国产精品三级在线| 国产精品视频区1| 亚洲色无码播放| 狠狠久久亚洲欧美专区| 久久天天躁狠狠躁夜夜躁| 亚洲最新中文字幕| 国内精品久久久久久久| 久久影视电视剧免费网站清宫辞电视| 欧美日韩一区二区三区| 51视频国产精品一区二区| 亚洲第一二三四五区| 久久精品国产亚洲一区二区| 欧美小视频在线观看| 成人免费自拍视频| 亚洲风情亚aⅴ在线发布| 欧美激情一区二区三区高清视频| 亚洲人成电影在线播放| 日韩欧美国产一区二区| 亚洲综合日韩中文字幕v在线| 91人成网站www| 91av在线播放视频| 日韩电影大全免费观看2023年上| 2023亚洲男人天堂| 成人av.网址在线网站| 68精品久久久久久欧美| 亚洲色图校园春色| 疯狂做受xxxx欧美肥白少妇| 日韩在线视频观看正片免费网站| 欧美精品免费在线| 国产欧美日韩丝袜精品一区| 亚洲a成v人在线观看| 最近免费中文字幕视频2019| 欧美激情18p| 日韩成人在线电影网| 成人免费在线视频网址| 欧美高清一级大片| 中文字幕亚洲专区| 国产成人+综合亚洲+天堂| 日韩精品高清在线| 亚洲性夜色噜噜噜7777| 伊人伊成久久人综合网小说| 日韩在线观看你懂的| 亚洲自拍中文字幕| 亚洲天堂视频在线观看| 欧美激情伊人电影| 成人伊人精品色xxxx视频| 97精品在线视频| 97在线视频一区| 中文字幕精品av| 国产精品白嫩美女在线观看| 亚洲深夜福利在线| 97国产精品久久| 日韩在线观看免费| 97超级碰在线看视频免费在线看| yw.139尤物在线精品视频| 成人妇女淫片aaaa视频| 日韩精品免费在线播放| 亚洲精品美女网站| 欧美精品久久久久久久久| 国产精品九九九| 欧美人交a欧美精品| 成人av资源在线播放| 亚洲大胆美女视频| 亚洲欧美日韩精品| 国产一区二区三区欧美| 欧美视频在线看| 欧美老少做受xxxx高潮| 久久久精品视频成人| 国产亚洲a∨片在线观看| 日韩av在线影视| 国产成人精品视频在线| 欧美区在线播放| 免费成人高清视频| 伊人久久大香线蕉av一区二区| 91精品国产综合久久香蕉| 国产玖玖精品视频| 欧美裸体xxxx| 国产精品电影一区| 久久香蕉国产线看观看av| 91免费看片网站| 国产精品wwwwww| 亚洲va男人天堂| 91精品中国老女人| 精品亚洲国产视频| 欧美激情视频给我| 神马久久桃色视频| 欧美老女人在线视频| 亚洲成人黄色在线| 成人午夜在线视频一区| 亚洲欧美国产精品久久久久久久| 日韩av电影在线网| 亚洲一区二区三区成人在线视频精品| 久久久精品一区二区| 久久精品亚洲国产| 91国产美女在线观看| xxxx性欧美| 欧美激情欧美狂野欧美精品| 亚洲国产欧美久久| 亚洲精品永久免费| 欧美国产日韩精品| 超碰91人人草人人干| 成人黄色av播放免费| 国产精品自产拍在线观看| 欧美日韩第一视频|