中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

Java多(duo)線(xian)程:多(duo)線(xian)程基礎(chu)知識

一、線(xian)程安全性

定義:多(duo)個(ge)線程(cheng)之間的操作無論采(cai)用何種執(zhi)行時序或(huo)交替方式,都(dou)要保證(zheng)不變(bian)性(xing)條(tiao)件不被破壞
    “共享(xiang)”:變量可以由(you)多個線程同(tong)時訪問;
    “可變(bian)”:變(bian)量(liang)的(de)值在其生(sheng)命周期內可以發生(sheng)改(gai)變(bian)
如果當多個線程訪問(wen)同一個可變(bian)的狀(zhuang)態(tai)變(bian)量(liang)時(shi),沒(mei)有(you)使(shi)用合適的同步(bu),那么程序將會出現錯誤。有(you)三種方式可以修(xiu)復該問(wen)題(ti):
  • 不在線(xian)程之間共(gong)享該變量。
  • 將狀態變量(liang)修改為不可變的變量(liang)。
  • 在訪問狀(zhuang)態(tai)變量時使用同步。
 
 
競(jing)態條件:
    最常見的(de)類(lei)型就是“先檢查(cha)后執行”操(cao)作,即通過一(yi)個(ge)可能(neng)失(shi)效的(de)觀測接(jie)口來決定下(xia)一(yi)步的(de)動作。
 

二、線(xian)程(cheng)啟(qi)動(dong)    

  •     繼承Thread類,重寫里面的run方法,用start方法啟動線程(cheng)
  •     實現Runnable接口,實現里面的run方法(fa),用new Thread(Runnable target).start()方法(fa)來啟動

start()和run()

    線(xian)程(cheng)的(de)(de)啟動并不是(shi)簡單的(de)(de)調用了(le)run方(fang)法,而是(shi)由(you)一(yi)(yi)個線(xian)程(cheng)調度器(qi)來(lai)分別調用所有(you)線(xian)程(cheng)的(de)(de)run方(fang)法,普(pu)通的(de)(de)run方(fang)法如果沒有(you)執(zhi)行(xing)(xing)完是(shi)不會(hui)返回的(de)(de),也就是(shi)會(hui)一(yi)(yi)直(zhi)執(zhi)行(xing)(xing)下去(qu),這樣run方(fang)法下面(mian)的(de)(de)方(fang)法就不可能會(hui)執(zhi)行(xing)(xing)了(le),可是(shi)線(xian)程(cheng)里的(de)(de)run方(fang)法卻不一(yi)(yi)樣,它只有(you)一(yi)(yi)定的(de)(de)CPU時(shi)(shi)間,執(zhi)行(xing)(xing)過后就給(gei)別的(de)(de)線(xian)程(cheng)了(le),這樣反復(fu)的(de)(de)把(ba)CPU的(de)(de)時(shi)(shi)間切來(lai)切去(qu),因(yin)為切換的(de)(de)速度很快,所以我們就感覺是(shi)很多線(xian)程(cheng)在同時(shi)(shi)運行(xing)(xing)一(yi)(yi)樣
    (01) mythread.run()是在(zai)“主線程main”中(zhong)調用的,該run()方法直接運行(xing)在(zai)“主線程main”上。
    (02) mythread.start()會啟(qi)(qi)動(dong)“線(xian)(xian)程mythread”,“線(xian)(xian)程mythread”啟(qi)(qi)動(dong)之后,會調用run()方法;此時的run()方法是運行在“線(xian)(xian)程mythread”上。
 

三、線程同(tong)步   

  • synchronized關(guan)鍵字(zi)
內置鎖(互斥鎖):
    在(zai)java中,每一(yi)(yi)個對(dui)象有(you)且僅(jin)有(you)一(yi)(yi)個同步(bu)鎖(suo)(suo)(suo)。這也意味(wei)著,同步(bu)鎖(suo)(suo)(suo)是(shi)依(yi)賴于對(dui)象而存在(zai)。線程在(zai)進入同步(bu)代碼塊之前(qian)會(hui)自動獲得(de)鎖(suo)(suo)(suo),并且在(zai)退出同步(bu)代碼塊時自動釋(shi)放(fang)鎖(suo)(suo)(suo)。同一(yi)(yi)時間最(zui)多只有(you)一(yi)(yi)個線程持有(you)該鎖(suo)(suo)(suo),其他線程必須等待(dai)或(huo)者阻塞(sai),直(zhi)到該線程釋(shi)放(fang)鎖(suo)(suo)(suo)。
    如果持有鎖的時間(jian)過長,將會帶來性能問題。
 
    實(shi)例鎖(suo) -- 鎖(suo)在某一個(ge)實(shi)例對象(xiang)上。如果該(gai)類是單例,那么該(gai)鎖(suo)也(ye)具有全局鎖(suo)的(de)概念(nian)。
                   實例鎖對應的(de)就是(shi)synchronized關鍵字。
    全局(ju)鎖(suo) -- 該鎖(suo)針對(dui)的是類,無(wu)論實例多少(shao)個對(dui)象(xiang),那么線程都共(gong)享該鎖(suo)。
             ;      全局鎖對應的(de)就是(shi)static synchronized(或(huo)者是(shi)鎖在該類的(de)class或(huo)者classloader對象上)。
  • volatile變(bian)量
    volatile相當于synchronized的(de)(de)(de)弱實現,也(ye)就是說volatile實現了類(lei)似(si)synchronized的(de)(de)(de)語義,卻又沒有鎖機(ji)制。它確保對volatile字段的(de)(de)(de)更新以可(ke)預見的(de)(de)(de)方式告知其他的(de)(de)(de)線程(cheng)。
    volatile包(bao)含(han)以下語義:
      (1)Java 存(cun)儲模型(xing)不會對valatile指(zhi)(zhi)令的(de)操作進行重排序(xu)(xu):這個保證對volatile變(bian)量(liang)的(de)操作時按(an)照指(zhi)(zhi)令的(de)出現順序(xu)(xu)執行的(de)。
      (2)volatile變(bian)量(liang)不會被緩存在寄存器中(只有(you)(you)擁(yong)有(you)(you)線程(cheng)可見(jian)(jian))或者其(qi)(qi)他對(dui)CPU不可見(jian)(jian)的(de)(de)地方,每次總(zong)是(shi)從主(zhu)存中讀(du)取volatile變(bian)量(liang)的(de)(de)結(jie)果(guo)。也(ye)就(jiu)是(shi)說對(dui)于(yu)volatile變(bian)量(liang)的(de)(de)修改(gai),其(qi)(qi)它線程(cheng)總(zong)是(shi)可見(jian)(jian)的(de)(de),并且不是(shi)使用自己線程(cheng)棧(zhan)內(nei)部的(de)(de)變(bian)量(liang)。也(ye)就(jiu)是(shi)在happens-before法則中,對(dui)一個valatile變(bian)量(liang)的(de)(de)寫操作后(hou),其(qi)(qi)后(hou)的(de)(de)任何讀(du)操作理解可見(jian)(jian)此寫操作的(de)(de)結(jie)果(guo)。
    盡(jin)管volatile變(bian)量的(de)(de)特性(xing)不(bu)錯(cuo),但是volatile并不(bu)能(neng)(neng)保(bao)證線程(cheng)安(an)全的(de)(de),也就是說volatile字段的(de)(de)操作不(bu)是原子(zi)(zi)性(xing)的(de)(de),volatile變(bian)量只能(neng)(neng)保(bao)證可見(jian)性(xing)(一個線程(cheng)修改后其它線程(cheng)能(neng)(neng)夠理解看到此變(bian)化(hua)后的(de)(de)結果),要想保(bao)證原子(zi)(zi)性(xing),目(mu)前為止(zhi)只能(neng)(neng)加鎖!
 

四(si)、線程(cheng)協作

線(xian)程(cheng)等待:

等待的原因可能是(shi)如下(xia)幾種情況:
     (1)sleep() 的作用是讓當前線程休眠,即當前線程會從“運行狀態”進入到“休眠(阻塞)狀態”。sleep()會指定休眠時間,線程休眠的時間會大于/等于該休眠時間;在線程重新被喚醒時,它會由“阻塞狀態”變成“就緒狀態”,從而等待cpu的調度執行。
     (2)通過調用join()方法使(shi)線(xian)(xian)程掛起,使(shi)自己(ji)等待(dai)另(ling)一個線(xian)(xian)程的結果,直(zhi)到另(ling)一個線(xian)(xian)程執行完畢為止。
     (3)通過調用wait()方法(fa)使線程掛起,直到(dao)線程得到(dao)了notify()和(he)notifyAll()消息,線程才會進入“可執(zhi)行”狀態(tai)。
     (4)yield()的作用是讓(rang)步。它(ta)能(neng)讓(rang)當(dang)前線(xian)程(cheng)由“運行狀(zhuang)態”進入(ru)到“就緒狀(zhuang)態”,從而讓(rang)其它(ta)具有(you)相同(tong)優先級的等(deng)待(dai)線(xian)程(cheng)獲(huo)取(qu)執(zhi)行權(quan);但(dan)是,并不能(neng)保證在當(dang)前線(xian)程(cheng)調用yield()之(zhi)后,其它(ta)具有(you)相同(tong)優先級的線(xian)程(cheng)就一定能(neng)獲(huo)得執(zhi)行權(quan);也有(you)可能(neng)是當(dang)前線(xian)程(cheng)又進入(ru)到“運行狀(zhuang)態”繼續運行!
 
注意:
  (01) wait()是讓(rang)線程由(you)“運行(xing)狀態(tai)”進(jin)入到“等待(dai)(阻塞(sai))狀態(tai)”,而yield()是讓(rang)線程由(you)“運行(xing)狀態(tai)”進(jin)入到“就緒狀態(tai)”。
  (02) wait()是會(hui)讓線程釋放它(ta)所持有對(dui)象的同步(bu)鎖(suo),而yield()方(fang)法不(bu)會(hui)釋放鎖(suo)。
  (03) sleep()使當前線程暫停執行一段時間,從而讓其他線程有機會繼續執行,但它并不釋放對象鎖
 
    wait():   
      “當前線程”在調用wait()時,必須擁有該對象的同步鎖。該線程調用wait()之后,會釋放該鎖;然后一直等待直到“其它線程”調用對象的同步鎖的notify()或notifyAll()方法。然后,該線程繼續等待直到它重新獲取“該對象的同步鎖”,然后就可以接著運行wait()后面的代碼。wait()的作用是讓“當前線程”等待,而“當前線程”是指正在cpu上運行的線程!因此調用wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)
  wait的東西一定要(yao)notify嗎?不一定,
    notify():
      notify() 執行(xing)該方法的(de)線(xian)程喚醒在對(dui)象(xiang)的(de)等(deng)待池(chi)中(zhong)等(deng)待的(de)一個(ge)線(xian)程,JVM從對(dui)象(xiang)的(de)等(deng)待池(chi)中(zhong)隨機選擇一個(ge)線(xian)程,把它(ta)轉到對(dui)象(xiang)的(de)鎖池(chi)中(zhong)。使(shi)線(xian)程由阻塞隊列進入就緒狀態。
    notifyAll():
      當前(qian)的線(xian)程已經放棄(qi)對資源的占(zhan)有(you),通知所有(you)的等待線(xian)程從wait()方法后的語句開(kai)始運行。
這里(li)要注(zhu)意一點:notify()和(he)notifyAll()方法只是喚醒等待該對象的鎖的線(xian)程,并不決定哪個線(xian)程能夠(gou)獲(huo)取到鎖.
  舉(ju)個簡單的例子:
  假如有三(san)個線程Thread1、Thread2和Thread3都在等待(dai)對(dui)象objectA的鎖,此時(shi)Thread4擁有對(dui)象objectA的鎖,當在Thread4中調用(yong)(yong)objectA.notify()方(fang)(fang)法(fa)之后,Thread1、Thread2和Thread3只有一(yi)個能被(bei)喚醒(xing)。注意,被(bei)喚醒(xing)不等于立刻就(jiu)獲(huo)取了objectA的鎖,假若在Thread4中調用(yong)(yong)objectA.notifyAll()方(fang)(fang)法(fa),則Thread1、Thread2和Thread3三(san)個線程都會(hui)被(bei)喚醒(xing),至于哪個線程接下來能夠(gou)獲(huo)取到(dao)objectA的鎖就(jiu)具體依(yi)賴(lai)于操作系統的調度(du)了。
  上面(mian)尤(you)其要注意(yi)一點,一個線程被喚醒不代表立即獲取了(le)對(dui)象(xiang)的(de)鎖,只有等調用(yong)完notify()或者notifyAll()并退出(chu)synchronized塊,釋放(fang)對(dui)象(xiang)鎖后,其余線程才可獲得鎖執行(xing)。
 
首先,wait()和notify(),notifyAll()是Object類(lei)的(de)方法,sleep()和yield()是Thread類(lei)的(de)方法。
  當(dang)然(ran)由于(yu)Thread類繼承了Object類,所以Thread也可以調用(yong)前面三個方法(fa)
  由于每個對象都擁有鎖,所以讓當前線程等待某個對象的鎖,當然應該通過這個對象來操作了。而不是用當前線程來操作,因為當前線程可能會等待多個對象的鎖,如果通過線程來操作,就非常復雜了。
 
(1).常用的wait方法(fa)有(you)wait()和wait(long timeout):
    void wait() 在其(qi)他線程調(diao)用此對象的 notify() 方法或(huo) notifyAll() 方法前,導致當(dang)前線程等待(dai)。 ;
    void wait(long timeout) 在其他線程(cheng)(cheng)調用此對象的 notify() 方法或(huo) notifyAll() 方法,或(huo)者超(chao)過指定的時間量前,導(dao)致(zhi)當前線程(cheng)(cheng)等(deng)待。
    wait()后,線程會釋放(fang)掉它(ta)所占有的“鎖(suo)標志”,從而(er)使線程所在對象中(zhong)的其(qi)它(ta)synchronized數據可被(bei)別的線程使用。
    wait()和(he)notify()因為(wei)會(hui)對對象的“鎖標志(zhi)”進(jin)行(xing)操作,所以它(ta)們必須在synchronized函(han)數或(huo)synchronized  block中(zhong)(zhong)進(jin)行(xing)調(diao)用。如果在non-synchronized函(han)數或(huo)non-synchronized block中(zhong)(zhong)進(jin)行(xing)調(diao)用,雖然能編譯通過,但在運 行(xing)時會(hui)發生IllegalMonitorStateException的異常(chang)。
 
(2).Thread.sleep(long millis),必(bi)須帶有一個時(shi)間(jian)參數。
    sleep(long)使當前線(xian)程進入停滯狀態,所以執(zhi)行sleep()的線(xian)程在指定的時間(jian)內肯定不會(hui)被執(zhi)行;
    sleep(long)可使優(you)先級低(di)的線程(cheng)得到執(zhi)(zhi)行的機(ji)會,當然也可以讓(rang)同優(you)先級和高優(you)先級的線程(cheng)有執(zhi)(zhi)行的機(ji)會;
    sleep(long)是不(bu)會釋(shi)放(fang)鎖(suo)標(biao)志的。
 
(3).yield()沒有(you)參數。
    sleep 方法(fa)使(shi)(shi)當前(qian)運行中的(de)線程睡(shui)眼一段時間(jian)(jian),進入不(bu)可運行狀態,這(zhe)段時間(jian)(jian)的(de)長(chang)短是(shi)由程序(xu)設(she)定的(de),yield 方法(fa)使(shi)(shi)當前(qian)線程讓出(chu)CPU占有權(quan),但讓出(chu)的(de)時間(jian)(jian)是(shi)不(bu)可設(she)定的(de)。
    yield()也不會釋放鎖標志。
 
    實際上,yield()方法對應(ying)了(le)如下操作: 先檢(jian)測當前是否有(you)相(xiang)同優先級的線程(cheng)處(chu)于同可運行(xing)(xing)狀態,如有(you),則把 CPU 的占有(you)權交給此線程(cheng),否則繼續運行(xing)(xing)原(yuan)來的線程(cheng)。所以yield()方法稱為(wei)“退讓”,它(ta)把運行(xing)(xing)機會讓給了(le)同等優先級的其(qi)他線程(cheng)。
 
    sleep方法允許較(jiao)低(di)優(you)(you)先(xian)(xian)級(ji)的線(xian)(xian)程獲(huo)得運(yun)(yun)行(xing)機(ji)(ji)會,但yield()方法執行(xing)時(shi)(shi),當(dang)前線(xian)(xian)程仍處在可運(yun)(yun)行(xing)狀態,所(suo)以不可能讓出較(jiao)低(di)優(you)(you)先(xian)(xian)級(ji)的線(xian)(xian)程些時(shi)(shi)獲(huo)得CPU占有(you)(you)權。 在一個運(yun)(yun)行(xing)系統中(zhong),如果較(jiao)高(gao)優(you)(you)先(xian)(xian)級(ji)的線(xian)(xian)程沒有(you)(you)調用 sleep 方法,又沒有(you)(you)受到 I/O阻塞,那么較(jiao)低(di)優(you)(you)先(xian)(xian)級(ji)線(xian)(xian)程只能等待所(suo)有(you)(you)較(jiao)高(gao)優(you)(you)先(xian)(xian)級(ji)的線(xian)(xian)程運(yun)(yun)行(xing)結束,才(cai)有(you)(you)機(ji)(ji)會運(yun)(yun)行(xing)。
 
    yield()只是使當前線程重(zhong)新回(hui)到可(ke)執行狀態(tai),所(suo)以(yi)執行yield()的線程有(you)可(ke)能在進入到可(ke)執行狀態(tai)后馬上又被執行。所(suo)以(yi)yield()只能使同優先級的線程有(you)執行的機會。
 

sleep和yield區別:

  1、sleep()方法會(hui)(hui)(hui)給(gei)其(qi)(qi)他(ta)線程(cheng)(cheng)運(yun)行的(de)機(ji)會(hui)(hui)(hui),而不考慮其(qi)(qi)他(ta)線程(cheng)(cheng)的(de)優(you)(you)先(xian)級,因此會(hui)(hui)(hui)給(gei)較低線程(cheng)(cheng)一個運(yun)行的(de)機(ji)會(hui)(hui)(hui);yield()方法只會(hui)(hui)(hui)給(gei)相同優(you)(you)先(xian)級或(huo)者更高優(you)(you)先(xian)級的(de)線程(cheng)(cheng)一個運(yun)行的(de)機(ji)會(hui)(hui)(hui)。 
  2、當線(xian)(xian)程(cheng)執(zhi)行了sleep(long millis)方(fang)法后,將(jiang)轉到阻塞狀態(tai),參數(shu)millis指定睡眠時間;當線(xian)(xian)程(cheng)執(zhi)行了yield()方(fang)法后,將(jiang)轉到就緒狀態(tai)。 
  3、sleep()方(fang)法(fa)聲明(ming)(ming)拋(pao)出InterruptedException異常,而(er)yield()方(fang)法(fa)沒有聲明(ming)(ming)拋(pao)出任何(he)異常 
 

為什么notify(), wait()等函數定義(yi)在Object中(zhong)(zhong),而不是Thread中(zhong)(zhong)?    

  Object中的wait(), notify()等函數,和(he)synchronized一樣,會(hui)對“對象(xiang)的同步鎖”進行操作。
wait()會使“當(dang)前線(xian)(xian)(xian)程(cheng)”等待,因(yin)為線(xian)(xian)(xian)程(cheng)進入等待狀態,所以線(xian)(xian)(xian)程(cheng)應(ying)該釋放它鎖(suo)持有的“同(tong)步(bu)鎖(suo)”,否(fou)則其(qi)它線(xian)(xian)(xian)程(cheng)獲取(qu)不到該“同(tong)步(bu)鎖(suo)”而(er)無法運行(xing)!那么:notify()是(shi)依(yi)據(ju)什么喚(huan)醒等待線(xian)(xian)(xian)程(cheng)的?或(huo)者說,wait()等待線(xian)(xian)(xian)程(cheng)和notify()之間是(shi)通過(guo)什么關聯(lian)起來的?答(da)案是(shi):依(yi)據(ju)“對(dui)象的同(tong)步(bu)鎖(suo)”。
  負責喚(huan)(huan)醒(xing)等(deng)(deng)待線(xian)(xian)程(cheng)(cheng)(cheng)的(de)(de)那個(ge)線(xian)(xian)程(cheng)(cheng)(cheng)(我們稱(cheng)為“喚(huan)(huan)醒(xing)線(xian)(xian)程(cheng)(cheng)(cheng)”),它(ta)只有在(zai)獲取(qu)“該對(dui)(dui)象的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)”(這(zhe)里的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)必須和(he)等(deng)(deng)待線(xian)(xian)程(cheng)(cheng)(cheng)的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)是(shi)同(tong)(tong)(tong)一個(ge)),并且調用(yong)notify()或notifyAll()方法之(zhi)后,才(cai)能喚(huan)(huan)醒(xing)等(deng)(deng)待線(xian)(xian)程(cheng)(cheng)(cheng)。雖(sui)然,等(deng)(deng)待線(xian)(xian)程(cheng)(cheng)(cheng)被喚(huan)(huan)醒(xing);但是(shi),它(ta)不能立刻執行,因為喚(huan)(huan)醒(xing)線(xian)(xian)程(cheng)(cheng)(cheng)還(huan)持有“該對(dui)(dui)象的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)”。必須等(deng)(deng)到(dao)喚(huan)(huan)醒(xing)線(xian)(xian)程(cheng)(cheng)(cheng)釋放了“對(dui)(dui)象的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)”之(zhi)后,等(deng)(deng)待線(xian)(xian)程(cheng)(cheng)(cheng)才(cai)能獲取(qu)到(dao)“對(dui)(dui)象的(de)(de)同(tong)(tong)(tong)步(bu)(bu)鎖(suo)(suo)”進(jin)而繼續運(yun)行。
  總之(zhi),notify(), wait()依賴于“同(tong)(tong)步鎖(suo)”,而(er)“同(tong)(tong)步鎖(suo)”是對(dui)象鎖(suo)持有(you)(you),并(bing)且每(mei)個對(dui)象有(you)(you)且僅有(you)(you)一個!這就是為(wei)什么notify(), wait()等函數定義(yi)在Object類,而(er)不是Thread類中的原(yuan)因(yin)。

 

Condition

Condition是在java 1.5中才(cai)出現的(de)(de)(de),它用(yong)來替代傳統的(de)(de)(de)Object的(de)(de)(de)wait()、notify()實(shi)現線(xian)程間(jian)的(de)(de)(de)協作,相比使用(yong)Object的(de)(de)(de)wait()、notify(),使用(yong)Condition的(de)(de)(de)await()、signal()這種方式實(shi)現線(xian)程間(jian)協作更加(jia)安全和高效。因此通常(chang)來說比較推(tui)薦(jian)使用(yong)Condition,Java阻(zu)塞隊列實(shi)際上是使用(yong)了Condition來模擬線(xian)程間(jian)協作。
  • Condition是(shi)個(ge)接口,基本(ben)的(de)方法就是(shi)await()和signal()方法;
  • Condition依(yi)賴于Lock接口,生(sheng)成一個(ge)Condition的基(ji)本代碼是lock.newCondition() 
  •  調用(yong)(yong)Condition的await()和signal()方法,都必須在(zai)lock保(bao)護(hu)之(zhi)內(nei),就是說(shuo)必須在(zai)lock.lock()和lock.unlock之(zhi)間才可以使用(yong)(yong)
  Conditon中的(de)await()對應(ying)Object的(de)wait();
  Condition中的signal()對應Object的notify();
  Condition中的(de)signalAll()對應Object的(de)notifyAll()。
 

五、線程中(zhong)斷  

    Java的(de)線程調度(du)不提(ti)供搶占(zhan)式中斷,而采用協作式的(de)中斷。其實(shi),協作式的(de)中斷,原(yuan)理很簡單,就是(shi)輪(lun)詢(xun)某個(ge)表示(shi)中斷的(de)標記。
        
    通常(chang),我們通過“標記(ji)(ji)”方式終(zhong)止處(chu)于(yu)“運行狀態”的(de)線程。其中,包括“中斷標記(ji)(ji)”和(he)“額(e)外添加標記(ji)(ji)”。

(01) 通過“中斷標記”終止線程

  形(xing)式如下:
@Override
publicvoid run() {
    while (!isInterrupted()) {
        // 執行(xing)任務...    }
}

 

說(shuo)明:isInterrupted()是判斷線程的中(zhong)斷標(biao)記(ji)(ji)是不(bu)是為(wei)true。當(dang)線程處于運行(xing)狀(zhuang)態(tai),并且我們需要終止它時;可以調用(yong)線程的interrupt()方法,使用(yong)線程的中(zhong)斷標(biao)記(ji)(ji)為(wei)true,即isInterrupted()會返回true。此時,就會退出while循環。
注(zhu)意(yi):interrupt()并(bing)不(bu)會(hui)終止處于“運行狀態”的線(xian)程!它會(hui)將線(xian)程的中斷標記設為(wei)true。

(02) 通過“額(e)外添加標(biao)記”。

  形式如(ru)下:
復制代碼
private volatile boolean flag = true;
protected void stopTask() {
    flag = false;
}

@Override
public void run() {
    while (flag) {
        // 執行任務...    }
}

 

復制代碼
說明:線(xian)(xian)程(cheng)中有一個flag標(biao)記,它的默認值是true;并且我們提供stopTask()來設置flag標(biao)記。當我們需要(yao)終止(zhi)該(gai)線(xian)(xian)程(cheng)時(shi),調用該(gai)線(xian)(xian)程(cheng)的stopTask()方法就(jiu)可以讓(rang)線(xian)(xian)程(cheng)退出while循環(huan)。
注(zhu)意:將(jiang)flag定義為volatile類型,是(shi)為了保證flag的(de)可見性。即(ji)其它線(xian)程通過stopTask()修(xiu)改了flag之后(hou),本(ben)線(xian)程能看到修(xiu)改后(hou)的(de)flag的(de)值(zhi)。
    通常(chang),我們通過“中斷”方(fang)式終止處于“阻塞(sai)狀態”的線程。
當線(xian)程(cheng)由于(yu)被(bei)調(diao)用了sleep(), wait(), join()等(deng)方法而進入阻塞狀態;若此時調(diao)用線(xian)程(cheng)的interrupt()將線(xian)程(cheng)的中斷標記(ji)設為(wei)true。由于(yu)處(chu)于(yu)阻塞狀態,中斷標記(ji)會被(bei)清除,同時產生(sheng)一個InterruptedException異常。將InterruptedException放(fang)在(zai)適當的為(wei)止就能終止線(xian)程(cheng)
@Override
public void run() {
    try {
        while (true) {
            // 執行任務...        }
    } catch (InterruptedException ie) {  
        // 由于產生(sheng)InterruptedException異常,退出while(true)循環,線程(cheng)終止!    }
}

 

注意(yi):對(dui)InterruptedException的捕獲務一般放(fang)在while(true)循(xun)環體的外面,這樣,在產(chan)生異常時就退出(chu)了while(true)循(xun)環。
 
 

參考(kao)資料:

   梁(liang)飛:Java并發編程(cheng)常識.pptx
 

posted @ 2017-09-27 16:17  ^_TONY_^  閱讀(1002)  評論(0)    收藏  舉報