一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java多線程及線程狀態(tài)轉(zhuǎn)換

 沙門空海 2018-11-20

以下內(nèi)容整理自:http://blog.csdn.net/wtyvhreal/article/details/44176369

線程:是指進(jìn)程中的一個(gè)執(zhí)行流程。  線程與進(jìn)程的區(qū)別:每個(gè)進(jìn)程都需要操作系統(tǒng)為其分配獨(dú)立的內(nèi)存地址空間,而同一進(jìn)程中的所有線程在同一塊地址空間中工作,這些線程可以共享同一塊內(nèi)存和系統(tǒng)資源。

Java實(shí)現(xiàn)多線程的方法有兩種,一是繼承Thread類、二是實(shí)現(xiàn)Runnable接口。

 

一、繼承Thread類

public class ThreadTest extends Thread {
    @Override
    public void run() {
        System.out.println("this thread name is:"+Thread.currentThread().getName());
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        ThreadTest t = new ThreadTest();
        t.setName("myTestThread");
        t.start();
    }
 
}

 

  • 繼承Thread后需要覆蓋run()來實(shí)現(xiàn)自己的業(yè)務(wù)邏輯;
  • 一個(gè)線程的啟動(dòng)是調(diào)用start方法,而不是run方法;
  • 當(dāng)給線程設(shè)置名稱的時(shí)候,就可以得到設(shè)置的線程名稱。

 

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

public class RunnableTest implements Runnable {
    @Override
    public void run() {
        System.out.println("this thread name is:"+Thread.currentThread().getName());
    }
     
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
        RunnableTest r = new RunnableTest();
        Thread t = new Thread(r);
        t.start();
    }
}
  • 實(shí)現(xiàn)Runnable接口需要實(shí)現(xiàn)run方法,在run方法里面實(shí)現(xiàn)自己的業(yè)務(wù)邏輯;
  • 實(shí)現(xiàn)Runnable接口的類自己不能啟動(dòng)線程,需要將此類的對象傳遞給Thread,由Thread的start方法啟動(dòng)。
  • main函數(shù)是java運(yùn)行啟動(dòng)的入口,它是由一個(gè)name叫main線程調(diào)用的;如果一個(gè)線程沒有專門設(shè)置名稱,程序會(huì)默認(rèn)的將名稱設(shè)置為Thread-num,num是從0開始累加的數(shù)字。

 三、線程的狀態(tài)轉(zhuǎn)換

  •  當(dāng)一個(gè)線程執(zhí)行了start方法后,不代表這個(gè)線程就會(huì)立即被執(zhí)行,只代表這個(gè)線程處于可運(yùn)行的狀態(tài),最終由OS的線程調(diào)度來決定哪個(gè)可運(yùn)行狀態(tài)下的線程被執(zhí)行。
  • 一個(gè)線程一次被選中執(zhí)行是有時(shí)間限制的,這個(gè)時(shí)間段叫做CPU的時(shí)間片,當(dāng)時(shí)間片用完但線程還沒有結(jié)束時(shí),這個(gè)線程又會(huì)變?yōu)榭蛇\(yùn)行狀態(tài),等待OS的再次調(diào)度;在運(yùn)行的線程里執(zhí)行Thread.yeild()方法同樣可以使當(dāng)前線程變?yōu)榭蛇\(yùn)行狀態(tài)。
  • 在一個(gè)運(yùn)行中的線程等待用戶輸入、調(diào)用Thread.sleep()、調(diào)用了其他線程的join()方法,則當(dāng)前線程變?yōu)樽枞麪顟B(tài)。
  • 阻塞狀態(tài)的線程用戶輸入完畢、sleep時(shí)間到、join的線程結(jié)束,則當(dāng)前線程由阻塞狀態(tài)變?yōu)榭蛇\(yùn)行狀態(tài)。
  • 運(yùn)行中的線程調(diào)用wait方法,此線程進(jìn)入等待隊(duì)列。
  • 運(yùn)行中的線程遇到synchronized同時(shí)沒有拿到對象的鎖標(biāo)記、等待隊(duì)列的線程wait時(shí)間到、等待隊(duì)列的線程被notify方法喚醒、有其他線程調(diào)用notifyAll方法,則線程變成鎖池狀態(tài)。
  • 鎖池狀態(tài)的線程獲得對象鎖標(biāo)記,則線程變成可運(yùn)行狀態(tài)。
  • 運(yùn)行中的線程run方法執(zhí)行完畢或main線程結(jié)束,則線程運(yùn)行結(jié)束。

 四、線程同步各個(gè)方法的區(qū)別

  • Thread.yield()當(dāng)前運(yùn)行的線程變成可運(yùn)行狀態(tài)。
  • t2.join() 使得當(dāng)前線程處于阻塞狀態(tài)直到t2線程執(zhí)行完畢。
  • Thread.sleep()使得當(dāng)前線程處于阻塞狀態(tài)直到sleep的時(shí)間結(jié)束。
  • wait、notify、notifyAll方法是Object類的方法,其調(diào)用環(huán)境必須有synchronized的同步塊中調(diào)用,否則會(huì)拋java.lang.IllegalMonitorStateException異常。

 

五、線程池

       多線程技術(shù)主要解決處理器單元內(nèi)多個(gè)線程執(zhí)行的問題,它可以顯著減少處理器單元的閑置時(shí)間,增加處理器單元的吞吐能力。

       假設(shè)一個(gè)服務(wù)器完成一項(xiàng)任務(wù)所需時(shí)間為:T1 創(chuàng)建線程時(shí)間,T2 在線程中執(zhí)行任務(wù)的時(shí)間,T3 銷毀線程時(shí)間。

  • 如果:T1 + T3 遠(yuǎn)大于 T2,則可以采用線程池,以提高服務(wù)器性能。
  •  一個(gè)線程池包括以下四個(gè)基本組成部分:

        1、線程池管理器(ThreadPool):用于創(chuàng)建并管理線程池,包括 創(chuàng)建線程池,銷毀線程池,添加新任務(wù);

        2、工作線程(PoolWorker):線程池中線程,在沒有任務(wù)時(shí)處于等待狀態(tài),可以循環(huán)的執(zhí)行任務(wù);

        3、任務(wù)接口(Task):每個(gè)任務(wù)必須實(shí)現(xiàn)的接口,以供工作線程調(diào)度任務(wù)的執(zhí)行,它規(guī)定了任務(wù)的入口,任務(wù)執(zhí)行完后的收尾工作,任務(wù)的執(zhí)行狀態(tài)等;

        4、任務(wù)隊(duì)列(taskQueue):用于存放沒有處理的任務(wù)。提供一種緩沖機(jī)制。

       線程池技術(shù)關(guān)注如何縮短或調(diào)整T1,T3時(shí)間的技術(shù),從而提高服務(wù)器程序性能。它把T1,T3分別安排在服務(wù)器程序的啟動(dòng)和結(jié)束的時(shí)間段或者一些空閑的時(shí)間段,這樣在服務(wù)器程序處理客戶請求時(shí),不會(huì)有T1,T3的開銷了。線程池不僅調(diào)整T1,T3產(chǎn)生的時(shí)間段,而且它還顯著減少了創(chuàng)建線程的數(shù)目,看一個(gè)例子:
        假設(shè)一個(gè)服務(wù)器一天要處理50000個(gè)請求,并且每個(gè)請求需要一個(gè)單獨(dú)的線程完成。在線程池中,線程數(shù)一般是固定的,所以產(chǎn)生線程總數(shù)不會(huì)超過線程池中線程的數(shù)目,而如果服務(wù)器不利用線程池來處理這些請求則線程總數(shù)為50000。一般線程池大小是遠(yuǎn)小于50000。所以利用線程池的服務(wù)器程序不會(huì)為了創(chuàng)建50000而在處理請求時(shí)浪費(fèi)時(shí)間,從而提高效率。

 
線程調(diào)度模型:分時(shí)調(diào)度模型和搶占式調(diào)度模型 。JVM采用搶占式調(diào)度模型。 所謂的多線程的并發(fā)運(yùn)行,其實(shí)是指宏觀上看,各個(gè)線程輪流獲得CPU的使用權(quán),分別執(zhí)行各自的任務(wù)。 (線程的調(diào)度不是跨平臺(tái),它不僅取決于java虛擬機(jī),它還依賴于操作系統(tǒng))
如果希望明確地讓一個(gè)線程給另外一個(gè)線程運(yùn)行的機(jī)會(huì),可以采取以下的辦法之一:

1、 調(diào)整各個(gè)線程的優(yōu)先級

2、 讓處于運(yùn)行狀態(tài)的線程調(diào)用Thread.sleep()方法

3、 讓處于運(yùn)行狀態(tài)的線程調(diào)用Thread.yield()方法

4、 讓處于運(yùn)行狀態(tài)的線程調(diào)用另一個(gè)線程的join()方法

調(diào)整各個(gè)線程的優(yōu)先級 Thread類的setPriority(int)和getPriority()方法分別用來設(shè)置優(yōu)先級和讀取優(yōu)先級。 如果希望程序能夠移值到各個(gè)操作系統(tǒng)中,應(yīng)該確保在設(shè)置線程的優(yōu)先級時(shí),只使用MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY這3個(gè)優(yōu)先級。
線程睡眠:當(dāng)線程在運(yùn)行中執(zhí)行了sleep()方法時(shí),它就會(huì)放棄CPU,轉(zhuǎn)到阻塞狀態(tài)。

 線程讓步:當(dāng)線程在運(yùn)行中執(zhí)行了Thread類的yield()靜態(tài)方法時(shí),如果此時(shí)具有相同優(yōu)先級的其它線程處于就緒狀態(tài),那么yield()方法將把當(dāng)前運(yùn)行的線程放到運(yùn)行池中并使另一個(gè)線程運(yùn)行。如果沒有相同優(yōu)先級的可運(yùn)行線程,則yield()方法什么也不做。

Sleep()方法和yield()方法都是Thread類的靜態(tài)方法,都會(huì)使當(dāng)前處于運(yùn)行狀態(tài)的線程放棄CPU,把運(yùn)行機(jī)會(huì)讓給別的線程,兩者的區(qū)別在于:1、sleep()方法會(huì)給其他線程運(yùn)行的機(jī)會(huì),而不考慮其他線程的優(yōu)先級,因此會(huì)給較低線程一個(gè)運(yùn)行的機(jī)會(huì);yield()方法只會(huì)給相同優(yōu)先級或者更高優(yōu)先級的線程一個(gè)運(yùn)行的機(jī)會(huì)。 2、當(dāng)線程執(zhí)行了sleep(long millis)方法后,將轉(zhuǎn)到阻塞狀態(tài),參數(shù)millis指定睡眠時(shí)間;當(dāng)線程執(zhí)行了yield()方法后,將轉(zhuǎn)到就緒狀態(tài)。 3、sleep()方法聲明拋出InterruptedException異常,而yield()方法沒有聲明拋出任何異常 4、sleep()方法比yield()方法具有更好的移植性
等待其它線程的結(jié)束:join() 當(dāng)前運(yùn)行的線程可以調(diào)用另一個(gè)線程的 join()方法,當(dāng)前運(yùn)行的線程將轉(zhuǎn)到阻塞狀態(tài),直到另一個(gè)線程運(yùn)行結(jié)束,它才恢復(fù)運(yùn)行。
定時(shí)器Timer:在JDK的java.util包中提供了一個(gè)實(shí)用類Timer, 它能夠定時(shí)執(zhí)行特定的任務(wù)。
線程的同步原子操作:根據(jù)Java規(guī)范,對于基本類型的賦值或者返回值操作,是原子操作。但這里的基本數(shù)據(jù)類型不包括long和double, 因?yàn)镴VM看到的基本存儲(chǔ)單位是32位,而long 和double都要用64位來表示。所以無法在一個(gè)時(shí)鐘周期內(nèi)完成。
自增操作(++):不是原子操作,因?yàn)樗婕暗揭淮巫x和一次寫。
原子操作:由一組相關(guān)的操作完成,這些操作可能會(huì)操縱與其它的線程共享的資源,為了保證得到正確的運(yùn)算結(jié)果,一個(gè)線程在執(zhí)行原子操作其間,應(yīng)該采取其他的措施使得其他的線程不能操縱共享資源。
同步代碼塊:為了保證每個(gè)線程能夠正常執(zhí)行原子操作,Java引入了同步機(jī)制,具體的做法是在代表原子操作的程序代碼前加上synchronized標(biāo)記,這樣的代碼被稱為同步代碼塊。
同步鎖:每個(gè)JAVA對象都有且只有一個(gè)同步鎖,在任何時(shí)刻,最多只允許一個(gè)線程擁有這把鎖。
當(dāng)一個(gè)線程試圖訪問帶有synchronized(this)標(biāo)記的代碼塊時(shí),必須獲得 this關(guān)鍵字引用的對象的鎖,在以下的兩種情況下,當(dāng)前線程有著不同的命運(yùn)。 1、 假如這個(gè)鎖已經(jīng)被其它的線程占用,JVM就會(huì)把這個(gè)線程放到本對象的鎖池中。本線程進(jìn)入阻塞狀態(tài)。鎖池中可能有很多的線程,等到其他的線程釋放了鎖,JVM就會(huì)從鎖池中隨機(jī)取出一個(gè)線程,使這個(gè)線程擁有鎖,并且轉(zhuǎn)到就緒狀態(tài)。 2、 假如這個(gè)鎖沒有被其他線程占用,本線程會(huì)獲得這把鎖,開始執(zhí)行同步代碼塊。 (一般情況下在執(zhí)行同步代碼塊時(shí)不會(huì)釋放同步鎖,但也有特殊情況會(huì)釋放對象鎖 如在執(zhí)行同步代碼塊時(shí),遇到異常而導(dǎo)致線程終止,鎖會(huì)被釋放;在執(zhí)行代碼塊時(shí),執(zhí)行了鎖所屬對象的wait()方法,這個(gè)線程會(huì)釋放對象鎖,進(jìn)入對象的等待池中)
線程同步的特征:

1、如果一個(gè)同步代碼塊和非同步代碼塊同時(shí)操作共享資源,仍然會(huì)造成對共享資源的競爭。因?yàn)楫?dāng)一個(gè)線程執(zhí)行一個(gè)對象的同步代碼塊時(shí),其他的線程仍然可以執(zhí)行對象的非同步代碼塊。(所謂的線程之間保持同步,是指不同的線程在執(zhí)行同一個(gè)對象的同步代碼塊時(shí),因?yàn)橐@得對象的同步鎖而互相牽制)

2、 每個(gè)對象都有唯一的同步鎖

3、 在靜態(tài)方法前面可以使用synchronized修飾符。

4、 當(dāng)一個(gè)線程開始執(zhí)行同步代碼塊時(shí),并不意味著必須以不間斷的方式運(yùn)行,進(jìn)入同步代碼塊的線程可以執(zhí)行Thread.sleep()或者執(zhí)行Thread.yield()方法,此時(shí)它并不釋放對象鎖,只是把運(yùn)行的機(jī)會(huì)讓給其他的線程。

5、 Synchronized聲明不會(huì)被繼承,如果一個(gè)用synchronized修飾的方法被子類覆蓋,那么子類中這個(gè)方法不在保持同步,除非用synchronized修飾。
線程安全的類:

     1、 這個(gè)類的對象可以同時(shí)被多個(gè)線程安全的訪問。

     2、 每個(gè)線程都能正常的執(zhí)行原子操作,得到正確的結(jié)果。

     3、 在每個(gè)線程的原子操作都完成后,對象處于邏輯上合理的狀態(tài)。
釋放對象的鎖:

    1、 執(zhí)行完同步代碼塊就會(huì)釋放對象的鎖

    2、 在執(zhí)行同步代碼塊的過程中,遇到異常而導(dǎo)致線程終止,鎖也會(huì)被釋放

    3、 在執(zhí)行同步代碼塊的過程中,執(zhí)行了鎖所屬對象的wait()方法,這個(gè)線程會(huì)釋放對象鎖,進(jìn)入對象的等待池。
死鎖: 當(dāng)一個(gè)線程等待由另一個(gè)線程持有的鎖,而后者正在等待已被第一個(gè)線程持有的鎖時(shí),就會(huì)發(fā)生死鎖。JVM不監(jiān)測也不試圖避免這種情況,因此保證不發(fā)生死鎖就成了程序員的責(zé)任。
避免死鎖 一個(gè)通用的經(jīng)驗(yàn)法則是:當(dāng)幾個(gè)線程都要訪問共享資源A、B、C 時(shí),保證每個(gè)線程都按照同樣的順序去訪問他們。
線程通信 :Java.lang.Object類中提供了兩個(gè)用于線程通信的方法 1、 wait():執(zhí)行了該方法的線程釋放對象的鎖,JVM會(huì)把該線程放到對象的等待池中。該線程等待其它線程喚醒 2、 notify():執(zhí)行該方法的線程喚醒在對象的等待池中等待的一個(gè)線程,JVM從對象的等待池中隨機(jī)選擇一個(gè)線程,把它轉(zhuǎn)到對象的鎖池中。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    色综合视频一区二区观看| 亚洲精品欧美精品一区三区 | 亚洲欧美一二区日韩高清在线| 99热中文字幕在线精品| 日本午夜免费观看视频| 日本精品中文字幕人妻| 少妇特黄av一区二区三区| 亚洲最新av在线观看| 午夜色午夜视频之日本| 欧美三级不卡在线观线看| 福利新区一区二区人口| 久久精品亚洲精品一区| 91欧美日韩精品在线| 国产专区亚洲专区久久| 亚洲性生活一区二区三区| 亚洲中文字幕高清乱码毛片| 国产又大又硬又粗又湿| 亚洲国产精品久久综合网| 亚洲中文在线观看小视频| 国语久精品在视频在线观看| 日韩综合国产欧美一区| 日韩专区欧美中文字幕| 日韩一区二区三区久久| 中文字幕亚洲精品乱码加勒比| 草草草草在线观看视频| 熟妇久久人妻中文字幕| 高潮日韩福利在线观看| 亚洲妇女作爱一区二区三区| 亚洲国产性生活高潮免费视频 | 精品人妻一区二区四区| 国产成人精品久久二区二区| 九九热精彩视频在线播放| 黑丝袜美女老师的小逼逼| 亚洲国产精品无遮挡羞羞| 国产老熟女超碰一区二区三区| 亚洲淫片一区二区三区| 亚洲精品成人综合色在线| 欧美一区二区日韩一区二区| 国产成人精品视频一区二区三区| 久久国产精品亚州精品毛片 | 久久国产青偷人人妻潘金莲|