国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

@Java | Thread & synchronized - [ 多線程 基本使用]

zhunjiee / 480人閱讀

摘要:線程線程是進(jìn)程中的一個(gè)實(shí)體,作為系統(tǒng)調(diào)度和分派的基本單位。下的線程看作輕量級(jí)進(jìn)程。因此,使用的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。需要注意的是,是線程自己從內(nèi)部拋出的,并不是方法拋出的。

本文及后續(xù)相關(guān)文章梳理一下關(guān)于多線程和同步鎖的知識(shí),平時(shí)只是應(yīng)用層面的了解,由于最近面試總是問(wèn)一些原理性的知識(shí),雖說(shuō)比較反感這種理論派,但是為了生計(jì)也必須掌握一番。(PS:并不是說(shuō)掌握原理不好,但是封裝就是為了更好的應(yīng)用,個(gè)人感覺(jué)沒(méi)必要為了學(xué)習(xí)而學(xué)習(xí),比較傾向于行動(dòng)派,能將原理應(yīng)用到實(shí)際才算參透,本文也僅僅是背書而已)
知識(shí)點(diǎn)

進(jìn)程:進(jìn)程就是一段程序的執(zhí)行過(guò)程,指在系統(tǒng)中能獨(dú)立運(yùn)行并作為資源分配的基本單位,它是由一組機(jī)器指令、數(shù)據(jù)和堆棧等組成的,是一個(gè)能獨(dú)立運(yùn)行的活動(dòng)實(shí)體。

線程:線程是進(jìn)程中的一個(gè)實(shí)體,作為系統(tǒng)調(diào)度和分派的基本單位。Linux下的線程看作輕量級(jí)進(jìn)程。

線程和進(jìn)程一樣分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止
多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)
多線程是指在同一程序中有多個(gè)順序流在執(zhí)行
多線程使用說(shuō)明 如何創(chuàng)建線程

實(shí)現(xiàn)Runnable接口

繼承Thread類

通過(guò)Callable和Future創(chuàng)建線程

1. 通過(guò)實(shí)現(xiàn)Runnable接口創(chuàng)建并運(yùn)行線程

- 實(shí)現(xiàn)Runnable接口

Public class A implements Runnable {
    public void run () {    // 必須實(shí)現(xiàn)run方法
        // 線程執(zhí)行的業(yè)務(wù)代碼
    }
}
上面實(shí)現(xiàn)了Runnable接口并通過(guò)run方法包裝了需要通過(guò)線程執(zhí)行的代碼

- 運(yùn)行線程
通過(guò)實(shí)現(xiàn)了Runnable接口的類的實(shí)例創(chuàng)建線程對(duì)象(Thread)來(lái)運(yùn)行線程,常用的Thread構(gòu)造方法:

Thread(Runnable threadOb,String threadName);
其中threadOb 是一個(gè)實(shí)現(xiàn)Runnable接口的類的實(shí)例threadName指定線程的名字

調(diào)用線程類中的start()方法運(yùn)行線程 new Thread(threadOb,threadName).start();(可創(chuàng)建多個(gè)線程對(duì)象運(yùn)行同一個(gè)Runnable接口實(shí)例的run方法,實(shí)現(xiàn)資源共享

PS:start()方法的調(diào)用后并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)?b>可運(yùn)行態(tài)(Runnable),等待CPU分配調(diào)度執(zhí)行
2. 繼承Thread類創(chuàng)建并運(yùn)行線程

- 繼承Thread類

public class A extends Thread {
    @Override
    public void run() {    // 重寫run方法
        // 線程執(zhí)行的業(yè)務(wù)代碼
    }
}
上面繼承了Runnable接口并通過(guò)重寫run方法包裝了需要通過(guò)線程執(zhí)行的代碼,通過(guò)源碼可以看到Thread類也是實(shí)現(xiàn)了Runnable接口的,所以本質(zhì)上和上一種方式無(wú)太大區(qū)別,不同的是Thread類不適合共享資源線程實(shí)現(xiàn)

- 運(yùn)行線程

同樣是調(diào)用線程類中的start()方法運(yùn)行線程,此時(shí)線程類為繼承Thread的類

3. 通過(guò)Callable和Future創(chuàng)建并運(yùn)行線程

- 實(shí)現(xiàn)Callable接口

public class A implements Callable {
    @Override  
    public T call() throws Exception  // 實(shí)現(xiàn)call()方法
    {  
        //  線程執(zhí)行的業(yè)務(wù)代碼
    }  
}
創(chuàng)建Callable接口的實(shí)現(xiàn)類(通過(guò)泛型制定線程執(zhí)行結(jié)束后的返回值類型),并實(shí)現(xiàn)call()方法,該call()方法將作為線程執(zhí)行體,并且有返回值(返回值類型為Callable接口泛型制定的類型)

- 使用FutureTask類來(lái)包裝Callable對(duì)象

FutureTask ft = new FutureTask<>(callableObj);
其中callableObjCallable實(shí)現(xiàn)類的實(shí)例,使用FutureTask類來(lái)包裝Callable對(duì)象,該FutureTask對(duì)象封裝了該Callable對(duì)象call()方法的返回值

- 運(yùn)行線程

通過(guò)FutureTask類的實(shí)例創(chuàng)建線程對(duì)象(Thread)來(lái)運(yùn)行線程,此時(shí)應(yīng)用的Thread`構(gòu)造方法:

Thread(FutureTask futureObj,String threadName);
其中futureObj 是一個(gè)FutureTask 類的實(shí)例threadName指定線程的名字

調(diào)用線程類中的start()方法運(yùn)行線程 new Thread(threadOb,threadName).start();
調(diào)用FutureTask對(duì)象的get()方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值

使用須知

多線程執(zhí)行的時(shí)候是無(wú)序的,即誰(shuí)先獲取到CPU資源就可以先執(zhí)行,隨機(jī)性比較大

如果start()方法重復(fù)調(diào)用,會(huì)出現(xiàn)java.lang.IllegalThreadStateException異常

直接繼承Thread類和實(shí)現(xiàn)接口方式創(chuàng)建線程的區(qū)別

直接繼承Thread類方便快捷,適合相對(duì)單一無(wú)序的多線程執(zhí)行

實(shí)現(xiàn)接口方式適合多個(gè)相同的程序代碼的線程去處理同一個(gè)資源

實(shí)現(xiàn)接口方式可以避免java中的單繼承的限制

實(shí)現(xiàn)接口方式增加程序的健壯性,代碼可以被多個(gè)線程共享,代碼和數(shù)據(jù)獨(dú)立

線程池只能放入實(shí)現(xiàn)Runablecallable類線程,不能直接放入繼承Thread的類

Java程序運(yùn)行首先會(huì)啟動(dòng)一個(gè)JVM進(jìn)程,然后至少啟動(dòng)兩個(gè)線程,即main線程垃圾收集線程

Thread常用方法說(shuō)明

sleep(long millis): 在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),可用TimeUnit.MILLISECONDS.sleep方法替換

join(): 等待調(diào)用join()的線程終止

使用方式

`Thread t = new AThread(); t.start(); t.join();`
join()的作用是將線程加入到當(dāng)前線程中,只有執(zhí)行完join()調(diào)用線程才能執(zhí)行后面的代碼

使用場(chǎng)景
正常情況下主線程不依賴子線程執(zhí)行完成而結(jié)束,當(dāng)主線程需要在子線程完成之后再結(jié)束時(shí),可使用此方法

yield(): 暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程

使用說(shuō)明
yield()只是將線程從運(yùn)行狀態(tài)轉(zhuǎn)到可運(yùn)行狀態(tài)(start()方法執(zhí)行后的狀態(tài)),不會(huì)導(dǎo)致線程轉(zhuǎn)到等待/睡眠/阻塞狀態(tài)

使用場(chǎng)景
yield()應(yīng)該做的是讓當(dāng)前運(yùn)行線程回到可運(yùn)行狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線程獲得運(yùn)行機(jī)會(huì)。因此,使用yield()的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。但是,實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€程還有可能被線程調(diào)度程序再次選中

PS:yield()方法執(zhí)行時(shí),當(dāng)前線程仍處在可運(yùn)行狀態(tài),所以,不可能讓出較低優(yōu)先級(jí)的線程些時(shí)獲得CPU占有權(quán)。在一個(gè)運(yùn)行系統(tǒng)中,如果較高優(yōu)先級(jí)的線程沒(méi)有調(diào)用sleep方法,又沒(méi)有受到IO 阻塞,那么,較低優(yōu)先級(jí)線程只能等待所有較高優(yōu)先級(jí)的線程運(yùn)行結(jié)束,才有機(jī)會(huì)運(yùn)行

setPriority(): 更改線程的優(yōu)先級(jí),優(yōu)先級(jí)高的線程會(huì)獲得較多的運(yùn)行機(jī)會(huì)
優(yōu)先級(jí)靜態(tài)常量MIN_PRIORITY=1,NORM_PRIORITY=5,MAX_PRIORITY=10

使用方式

Thread t1 = new Thread("t1");
Thread t2 = new Thread("t2");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);

使用說(shuō)明
Thread類的setPriority()和getPriority()方法分別用來(lái)設(shè)置和獲取線程的優(yōu)先級(jí)。
每個(gè)線程都有默認(rèn)的優(yōu)先級(jí)。主線程的默認(rèn)優(yōu)先級(jí)為Thread.NORM_PRIORITY。
線程的優(yōu)先級(jí)有繼承關(guān)系,比如A線程中創(chuàng)建了B線程,那么B將和A具有相同的優(yōu)先級(jí)。
JVM提供了10個(gè)線程優(yōu)先級(jí),但與常見(jiàn)的操作系統(tǒng)都不能很好的映射。如果希望程序能移植到各個(gè)操作系統(tǒng)中,應(yīng)該僅僅使用Thread類有以下三個(gè)靜態(tài)常量作為優(yōu)先級(jí),這樣能保證同樣的優(yōu)先級(jí)采用了同樣的調(diào)度方式

interrupt(): 將線程對(duì)象的中斷標(biāo)識(shí)設(shè)成true

使用說(shuō)明

中斷只是一種協(xié)作機(jī)制,Java沒(méi)有給中斷增加任何語(yǔ)法,中斷的過(guò)程完全需要程序員自己實(shí)現(xiàn)。若要中斷一個(gè)線程,你需要手動(dòng)調(diào)用該線程的interrupted方法,該方法也僅僅是將線程對(duì)象的中斷標(biāo)識(shí)設(shè)成true;接著你需要自己寫代碼不斷地檢測(cè)當(dāng)前線程的標(biāo)識(shí)位;如果為true,表示別的線程要求這條線程中斷,此時(shí)究竟該做什么需要你自己寫代碼實(shí)現(xiàn)

每個(gè)線程對(duì)象中都有一個(gè)標(biāo)識(shí),用于表示線程是否被中斷;該標(biāo)識(shí)位為true表示中斷,為false表示未中斷

通過(guò)調(diào)用線程對(duì)象的interrupt方法將該線程的標(biāo)識(shí)位設(shè)為true;可以在別的線程中調(diào)用,也可以在自己的線程中調(diào)用

使用方式

在調(diào)用阻塞方法時(shí)正確處理InterruptedException異常

設(shè)置中斷監(jiān)聽(tīng)(另一種方式)

Thread t1 = new Thread( new Runnable(){
       public void run(){
           // 若未發(fā)生中斷,就正常執(zhí)行任務(wù)
           while(!Thread.currentThread.isInterrupted()){
               // 正常任務(wù)代碼……
           }
   
           // 中斷的處理代碼……
           doSomething();
       }
   } ).start();

觸發(fā)中斷

t1.interrupt();

interrupt方法使用參考鏈接
大閑人柴毛毛

wait(): 主動(dòng)釋放對(duì)象鎖,同時(shí)本線程休眠,直到有其它線程調(diào)用對(duì)象的notify()喚醒該線程,重新獲取對(duì)象鎖并執(zhí)行(wait()方法屬于Object中的方法,并不屬于Thread類)

notify(): 喚醒調(diào)用notify()對(duì)象的線程,notify()調(diào)用后,并不是馬上就釋放對(duì)象鎖的,而是在相應(yīng)的synchronized(){}語(yǔ)句塊執(zhí)行結(jié)束,自動(dòng)釋放鎖后,JVM會(huì)在wait()對(duì)象鎖的線程中隨機(jī)選取一線程,賦予其對(duì)象鎖,喚醒線程,繼續(xù)執(zhí)行

Thread幾個(gè)方法比較

1.sleep()yield()的區(qū)別

sleep()使當(dāng)前線程進(jìn)入停滯狀態(tài),所以執(zhí)行sleep()的線程在指定的時(shí)間內(nèi)肯定不會(huì)被執(zhí)行;yield()只是使當(dāng)前線程重新回到可執(zhí)行狀態(tài),所以執(zhí)行yield()的線程有可能在進(jìn)入到可執(zhí)行狀態(tài)后馬上又被執(zhí)行

sleep方法使當(dāng)前運(yùn)行中的線程睡眼一段時(shí)間,進(jìn)入不可運(yùn)行狀態(tài),這段時(shí)間的長(zhǎng)短是由程序設(shè)定的,yield方法使當(dāng)前線程讓出CPU占有權(quán),但讓出的時(shí)間是不可設(shè)定的。實(shí)際上,yield()方法對(duì)應(yīng)了如下操作:先檢測(cè)當(dāng)前是否有相同優(yōu)先級(jí)的線程處于同可運(yùn)行狀態(tài),如有,則把CPU的占有權(quán)交給此線程,否則,繼續(xù)運(yùn)行原來(lái)的線程。所以yield()方法稱為"退讓",它把運(yùn)行機(jī)會(huì)讓給了同等優(yōu)先級(jí)的其他線程

sleep方法允許較低優(yōu)先級(jí)的線程獲得運(yùn)行機(jī)會(huì),但yield()方法執(zhí)行時(shí),當(dāng)前線程仍處在可運(yùn)行狀態(tài),所以,不可能讓出較低優(yōu)先級(jí)的線程些時(shí)獲得CPU占有權(quán)。在一個(gè)運(yùn)行系統(tǒng)中,如果較高優(yōu)先級(jí)的線程沒(méi)有調(diào)用 sleep方法,又沒(méi)有受到IO阻塞,那么,較低優(yōu)先級(jí)線程只能等待所有較高優(yōu)先級(jí)的線程運(yùn)行結(jié)束,才有機(jī)會(huì)運(yùn)行

2.wait()sleep()區(qū)別

共同點(diǎn):

他們都是在多線程的環(huán)境下,都可以在程序的調(diào)用處阻塞指定的毫秒數(shù),并返回

wait()和sleep()都可以通過(guò)interrupt()方法 打斷線程的暫停狀態(tài),從而使線程立刻拋出InterruptedException

如果線程A希望立即結(jié)束線程B,則可以對(duì)線程B對(duì)應(yīng)的Thread實(shí)例調(diào)用interrupt方法。如果此刻線程B正在wait/sleep /join,則線程B會(huì)立刻拋出InterruptedException,在catch() {} 中直接return即可安全地結(jié)束線程。

需要注意的是,InterruptedException是線程自己從內(nèi)部拋出的,并不是interrupt()方法拋出的。對(duì)某一線程調(diào)用interrupt()時(shí),如果該線程正在執(zhí)行普通的代碼,那么該線程根本就不會(huì)拋出InterruptedException。但是,一旦該線程進(jìn)入到wait()/sleep()/join()后,就會(huì)立刻拋出InterruptedException

不同點(diǎn):

sleep(),yield()等是Thread類的方法

wait()和notify()等是Object的方法

每個(gè)對(duì)象都有一個(gè)鎖來(lái)控制同步訪問(wèn)。Synchronized關(guān)鍵字可以和對(duì)象的鎖交互,來(lái)實(shí)現(xiàn)線程的同步。sleep方法沒(méi)有釋放鎖,而wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法

wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用

簡(jiǎn)單來(lái)說(shuō): 

sleep()睡眠時(shí),保持對(duì)象鎖,仍然占有該鎖;

而wait()睡眠時(shí),釋放對(duì)象鎖。

wait()和sleep()都可以通過(guò)interrupt()方法打斷線程的暫停狀態(tài),從而使線程立刻拋出InterruptedException(但不建議使用該方法)

sleep()方法

sleep()使當(dāng)前線程進(jìn)入停滯狀態(tài)(阻塞當(dāng)前線程),讓出CPU的使用、目的是不讓當(dāng)前線程獨(dú)自霸占該進(jìn)程所獲的CPU資源,以留一定時(shí)間給其他線程執(zhí)行的機(jī)會(huì);

sleep()是Thread類的Static的方法;因此他不能改變對(duì)象的機(jī)鎖,所以當(dāng)在一個(gè)Synchronized塊中調(diào)用Sleep()方法是,線程雖然休眠了,但是對(duì)象的機(jī)鎖并沒(méi)有被釋放,其他線程無(wú)法訪問(wèn)這個(gè)對(duì)象(即使休眠也持有對(duì)象鎖

在sleep()休眠時(shí)間期滿后,該線程不一定會(huì)立即執(zhí)行,這是因?yàn)槠渌€程可能正在運(yùn)行而且沒(méi)有被調(diào)度為放棄執(zhí)行,除非此線程具有更高的優(yōu)先級(jí)

wait()方法

wait()方法是Object類里的方法;當(dāng)一個(gè)線程執(zhí)行到wait()方法時(shí),它就進(jìn)入到一個(gè)和該對(duì)象相關(guān)的等待池中,同時(shí)失去(釋放)了對(duì)象的機(jī)鎖(暫時(shí)失去機(jī)鎖,wait(long timeout)超時(shí)時(shí)間到后還需要返還對(duì)象鎖);其他線程可以訪問(wèn);

wait()使用notify或者notifyAlll或者指定睡眠時(shí)間來(lái)喚醒當(dāng)前等待池中的線程。

wait()必須放在synchronized block中,否則會(huì)在程序runtime時(shí)扔出java.lang.IllegalMonitorStateException異常。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/69490.html

相關(guān)文章

  • @Java | Thread &amp; synchronized - [ 線程同步鎖 基本使用]

    摘要:線程同步方法是通過(guò)鎖來(lái)實(shí)現(xiàn),每個(gè)對(duì)象都有切僅有一個(gè)鎖,這個(gè)鎖與一個(gè)特定的對(duì)象關(guān)聯(lián),線程一旦獲取了對(duì)象鎖,其他訪問(wèn)該對(duì)象的線程就無(wú)法再訪問(wèn)該對(duì)象的其他非同步方法對(duì)于靜態(tài)同步方法,鎖是針對(duì)這個(gè)類的,鎖對(duì)象是該類的對(duì)象。 對(duì)實(shí)現(xiàn)了Runnable或者Callable接口類,可以通過(guò)多線程執(zhí)行同一實(shí)例的run或call方法,那么對(duì)于同一實(shí)例中的局部變量(非方法變量)就會(huì)有多個(gè)線程進(jìn)行更改或讀取...

    Michael_Lin 評(píng)論0 收藏0
  • @Java | Thread &amp; synchronized - [ 線程 理論知識(shí)]

    摘要:死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。枚舉程序中的線程。強(qiáng)迫一個(gè)線程等待。通知一個(gè)線程繼續(xù)運(yùn)行。 一. 線程狀態(tài)轉(zhuǎn)換圖 showImg(https://segmentfault.com/img/bV38ef?w=968&h=680); 線程間的狀態(tài)轉(zhuǎn)換說(shuō)明: 新建(new)...

    harryhappy 評(píng)論0 收藏0
  • Java線程&amp;高并發(fā)

    摘要:線程啟動(dòng)規(guī)則對(duì)象的方法先行發(fā)生于此線程的每一個(gè)動(dòng)作。所以局部變量是不被多個(gè)線程所共享的,也就不會(huì)出現(xiàn)并發(fā)問(wèn)題。通過(guò)獲取到數(shù)據(jù),放入當(dāng)前線程處理完之后將當(dāng)前線程中的信息移除。主線程必須在啟動(dòng)其他線程后立即調(diào)用方法。 一、線程安全性 定義:當(dāng)多個(gè)線程訪問(wèn)某個(gè)類時(shí),不管運(yùn)行時(shí)環(huán)境采用何種調(diào)度方式,或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個(gè)類都能表現(xiàn)出正確的行...

    SQC 評(píng)論0 收藏0
  • 深入理解 Java 線程系列(1)——一個(gè)簡(jiǎn)單需求的并行改造 &amp; Java線程的通信問(wèn)題

    摘要:所以接下來(lái),我們需要簡(jiǎn)單的介紹下多線程中的并發(fā)通信模型。比如中,以及各種鎖機(jī)制,均為了解決線程間公共狀態(tài)的串行訪問(wèn)問(wèn)題。 并發(fā)的學(xué)習(xí)門檻較高,相較單純的羅列并發(fā)編程 API 的枯燥被動(dòng)學(xué)習(xí)方式,本系列文章試圖用一個(gè)簡(jiǎn)單的栗子,一步步結(jié)合并發(fā)編程的相關(guān)知識(shí)分析舊有實(shí)現(xiàn)的不足,再實(shí)現(xiàn)邏輯進(jìn)行分析改進(jìn),試圖展示例子背后的并發(fā)工具與實(shí)現(xiàn)原理。 本文是本系列的第一篇文章,提出了一個(gè)簡(jiǎn)單的業(yè)務(wù)場(chǎng)景...

    ruicbAndroid 評(píng)論0 收藏0
  • Java線程基礎(chǔ)(一)——線程與鎖

    摘要:一線程的基本概念單線程簡(jiǎn)單的說(shuō),單線程就是進(jìn)程中只有一個(gè)線程。多線程由一個(gè)以上線程組成的程序稱為多線程程序。當(dāng)線程調(diào)用完方法進(jìn)入后會(huì)自動(dòng)釋放鎖,線程獲得鎖。 一、線程的基本概念 1.1 單線程 簡(jiǎn)單的說(shuō),單線程就是進(jìn)程中只有一個(gè)線程。單線程在程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來(lái),前面的必須處理好,后面的才會(huì)執(zhí)行。 Java示例: public class SingleThrea...

    WelliJhon 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<