Java 2實用教程第4版_第12章_Java多線程機制_第1頁
Java 2實用教程第4版_第12章_Java多線程機制_第2頁
Java 2實用教程第4版_第12章_Java多線程機制_第3頁
Java 2實用教程第4版_第12章_Java多線程機制_第4頁
Java 2實用教程第4版_第12章_Java多線程機制_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、第 1 頁注意:開始用功了注意:開始用功了!第 2 頁Java2實用教程實用教程(第第4版版) 第第12章章配合例子源代碼一起使用例子源代碼一起使用Power point 制作:耿祥義 張躍平JavaJava多線程機制多線程機制 第 3 頁導(dǎo)讀導(dǎo)讀主要內(nèi)容主要內(nèi)容Java中的線程中的線程Thread類與線程的創(chuàng)建類與線程的創(chuàng)建線程的常用方法線程的常用方法線程同步線程同步協(xié)調(diào)同步的線程協(xié)調(diào)同步的線程線程聯(lián)合線程聯(lián)合GUI線程線程計時器線程計時器線程第 4 頁12.1 進程與線程進程與線程 12.1.1 操作系統(tǒng)與進程操作系統(tǒng)與進程 程序程序是一段靜態(tài)的代碼,它是一段靜態(tài)的代碼,它是應(yīng)用軟件執(zhí)行的

2、藍本。是應(yīng)用軟件執(zhí)行的藍本。 進程進程是程序的一次動態(tài)執(zhí)行是程序的一次動態(tài)執(zhí)行過程,它對應(yīng)了從代碼加載、執(zhí)過程,它對應(yīng)了從代碼加載、執(zhí)行至執(zhí)行完畢的一個完整過程,行至執(zhí)行完畢的一個完整過程,這個過程也是進程本身從產(chǎn)生、這個過程也是進程本身從產(chǎn)生、發(fā)展至消亡的過程。發(fā)展至消亡的過程。 現(xiàn)代操作系統(tǒng)可以同時管理現(xiàn)代操作系統(tǒng)可以同時管理一個計算機系統(tǒng)中的多個進程,一個計算機系統(tǒng)中的多個進程,即可以讓計算機系統(tǒng)中的多個進即可以讓計算機系統(tǒng)中的多個進程輪流使用程輪流使用CPUCPU資源。資源。第 5 頁12.1.2 進程與線程進程與線程 線程是比進程更小的執(zhí)行線程是比進程更小的執(zhí)行單位,一個進程在其執(zhí)行

3、過程單位,一個進程在其執(zhí)行過程中,可以產(chǎn)生多個線程,形成中,可以產(chǎn)生多個線程,形成多條執(zhí)行線索,每條線索,即多條執(zhí)行線索,每條線索,即每個線程也有它自身的產(chǎn)生、每個線程也有它自身的產(chǎn)生、存在和消亡的過程。存在和消亡的過程。 線程間可以共享進程中的線程間可以共享進程中的某些內(nèi)存單元某些內(nèi)存單元(包括代碼與數(shù)包括代碼與數(shù)據(jù)據(jù)),線程的中斷與恢復(fù)可以,線程的中斷與恢復(fù)可以更加節(jié)省系統(tǒng)的開銷。更加節(jié)省系統(tǒng)的開銷。第 6 頁12.2 Java中的線程中的線程 12.2.1 Java的多線程機制的多線程機制 JavaJava語言的一大特性點就是內(nèi)置對多線程的支持。語言的一大特性點就是內(nèi)置對多線程的支持。

4、Java Java虛擬機快速地把控制從一個線程切換到另一虛擬機快速地把控制從一個線程切換到另一個線程。個線程。這些線程將被輪流執(zhí)行,使得每個線程都有這些線程將被輪流執(zhí)行,使得每個線程都有機會使用機會使用CPUCPU資源。資源。第 7 頁12.2.2 主主線程(線程(mainmain線程)線程) 每個每個Java應(yīng)用程序都有一個缺省的主線程。應(yīng)用程序都有一個缺省的主線程。 當(dāng)當(dāng)JVM(Java Virtual Machine 虛擬機)加載代碼,發(fā)現(xiàn)虛擬機)加載代碼,發(fā)現(xiàn)main方法之后,就會啟動一個線程,這個線程稱為方法之后,就會啟動一個線程,這個線程稱為“主線程主線程”(main線程),該線程

5、負責(zé)執(zhí)行線程),該線程負責(zé)執(zhí)行main方法。方法。 JVM一直要等到一直要等到Java應(yīng)用程序中的所有線程都結(jié)束之后,才應(yīng)用程序中的所有線程都結(jié)束之后,才結(jié)束結(jié)束Java應(yīng)用程序應(yīng)用程序 。 第 8 頁12.2.3 線程的狀態(tài)與生命周期線程的狀態(tài)與生命周期 建的線程在它的一個完整的生命周期中通常要經(jīng)歷如下的四建的線程在它的一個完整的生命周期中通常要經(jīng)歷如下的四種狀態(tài):種狀態(tài):1新建新建: 當(dāng)一個當(dāng)一個Thread類或其子類的對象被聲明并創(chuàng)建時,新生的線程對象類或其子類的對象被聲明并創(chuàng)建時,新生的線程對象處于新建狀態(tài)。處于新建狀態(tài)。2運行運行 :線程必須調(diào)用線程必須調(diào)用startstart()(

6、)方法(從父類繼承的方法)通知方法(從父類繼承的方法)通知JVMJVM,這樣這樣JVMJVM就會知道又有一個新一個線程排隊等候切換了。一旦輪到它來享用就會知道又有一個新一個線程排隊等候切換了。一旦輪到它來享用CPUCPU資資源時,此線程的就可以脫離創(chuàng)建它的主線程獨立開始自己的生命周期了。源時,此線程的就可以脫離創(chuàng)建它的主線程獨立開始自己的生命周期了。 3中斷中斷:有有4 4種原因的中斷:種原因的中斷: JVM JVM將將CPUCPU資源從當(dāng)前線程切換給其他線程,使本線程讓出資源從當(dāng)前線程切換給其他線程,使本線程讓出CPUCPU的使用權(quán)的使用權(quán)處于中斷狀態(tài)。處于中斷狀態(tài)。 線程使用線程使用CPU

7、CPU資源期間,執(zhí)行了資源期間,執(zhí)行了sleep(int millsecond)sleep(int millsecond)方法,使當(dāng)前線方法,使當(dāng)前線程進入休眠狀。程進入休眠狀。 線程使用線程使用CPUCPU資源期間,執(zhí)行了資源期間,執(zhí)行了wait()wait()方法。方法。 線程使用線程使用CPUCPU資源期間,執(zhí)行某個操作進入阻塞狀態(tài)。資源期間,執(zhí)行某個操作進入阻塞狀態(tài)。4死亡死亡 :處于死亡狀態(tài)的線程不具有繼續(xù)運行的能力。線程釋放了實體。處于死亡狀態(tài)的線程不具有繼續(xù)運行的能力。線程釋放了實體。 第 9 頁 例子例子1(Example12_1.java )通過分析運行結(jié)果闡述線程的4種狀態(tài)

8、。例子1在主線程中用Thread的子類創(chuàng)建了兩個線程(SpeakElephant.java , SpeakCar.java ),這兩個線程分別在命令行窗口輸出20句“大象”和“轎車”;主線程在命令行窗口輸出15句“主人”。 例子例子1的運行效果如圖12.4。 例子例子1在不同的計算機運行或在同一臺計算機反復(fù)運行的結(jié)果不盡相同,輸出結(jié)果依賴當(dāng)前CPU資源的使用情況。 第 10 頁12.2.4 線程調(diào)度與優(yōu)先級線程調(diào)度與優(yōu)先級 處于就緒狀態(tài)的線程首先進入就緒隊列排隊等候處于就緒狀態(tài)的線程首先進入就緒隊列排隊等候CPU資源,同一時刻在就緒隊列中的線程可能有多個。資源,同一時刻在就緒隊列中的線程可能有

9、多個。Java虛擬機(虛擬機(JVM)中的線程調(diào)度器負責(zé)管理線程,中的線程調(diào)度器負責(zé)管理線程,調(diào)度器把線程的優(yōu)先級分為調(diào)度器把線程的優(yōu)先級分為10個級別,分別用個級別,分別用Thread類中的類常量表示。類中的類常量表示。 Java調(diào)度器的任務(wù)是使高優(yōu)先級的線程能始終運行,調(diào)度器的任務(wù)是使高優(yōu)先級的線程能始終運行,一旦時間片有空閑,則使具有同等優(yōu)先級的線程以輪流一旦時間片有空閑,則使具有同等優(yōu)先級的線程以輪流的方式順序使用時間片。的方式順序使用時間片。 第 11 頁12.3 ThreadThread類與線程的創(chuàng)建類與線程的創(chuàng)建 12.3.1 使用使用Thread的子類的子類 在在JavaJav

10、a語言中,用語言中,用ThreadThread類或子類創(chuàng)建線程對象。類或子類創(chuàng)建線程對象。 在編寫在編寫ThreadThread類的子類時,需要重寫父類的類的子類時,需要重寫父類的run()run()方法,其目的是規(guī)定線程的具體操作,否則線程就什方法,其目的是規(guī)定線程的具體操作,否則線程就什么也不做,因為父類的么也不做,因為父類的run()run()方法中沒有任何操作語方法中沒有任何操作語句。句。第 12 頁12.3.2 使用使用ThreadThread類類 創(chuàng)建線程的另一個途徑就是用Thread類直接創(chuàng)建線程對象。使用Thread創(chuàng)建線程通常使用的構(gòu)造方法是: Thread(Runnable

11、 target) 該構(gòu)造方法中的參數(shù)是一個Runnable類型的接口。 在創(chuàng)建線程對象時必須向構(gòu)造方法的參數(shù)傳遞一個實現(xiàn)Runnable接口類的實例,該實例對象稱作所創(chuàng)線程的目標(biāo)對象,當(dāng)線程調(diào)用start()方法后,一旦輪到它來享用CPU資源,目標(biāo)對象就會自動調(diào)用接口中的run()方法(接口回調(diào))。 例子例子2 (Example12_2.java, ElephantTarget.java , CarTarget.java )和前面的例子例子1不同,不使用Thread類的子類創(chuàng)建線程,而是使用Thread類創(chuàng)建speakElephant和speakCar線程,請讀者注意比較例子1和例子2的細微差

12、別。 第 13 頁 線程間可以共享相同的內(nèi)存單元(包括代碼與數(shù)據(jù)),并利用這些共享單元來實現(xiàn)數(shù)據(jù)交換、實時通信與必要的同步操作。 例子例子3(Example12_3.java , House.java )中使用Thread類創(chuàng)建兩個模擬貓和狗的線程,貓和狗共享房屋中的一桶水,即房屋是線程的目標(biāo)對象,房屋中的一桶水被貓和狗共享。貓和狗輪流喝水(狗喝的多,貓喝的少),當(dāng)水被喝盡時,貓和狗進入死亡狀態(tài)。貓或狗在輪流喝水的過程中,主動休息片刻(讓Thread類調(diào)用sleep(int n)進入中斷狀態(tài)),而不是等到被強制中斷喝水。 第 14 頁12.3.3 目標(biāo)對象與線程的關(guān)系目標(biāo)對象與線程的關(guān)系 從對

13、象和對象之間的關(guān)系角度上看,目標(biāo)對象和線程的關(guān)系有以下兩種情景。 1.目標(biāo)對象和線程完全解耦 目標(biāo)對象沒有組合線程對象.目標(biāo)對象經(jīng)常需要通過獲得線程的名字(因為無法獲得線程對象的引用)以便確定是哪個線程正在占用CPU資源,即被JVM正在執(zhí)行的線程。 2.目標(biāo)對象組合線程(弱耦合) 目標(biāo)對象可以組合線程.目標(biāo)對象類組合線程對象時, 目標(biāo)對象可以通過獲得線程對象的引用. 例子例子4中中( (Example12_4.java Example12_4.java , , House.java House.java ) ),線程cat和dog在House中,請注意例子4與例子3的區(qū)別 .第 15 頁12.

14、3.4 關(guān)于關(guān)于run()run()方法啟動的次數(shù)方法啟動的次數(shù) 對于具有相同目標(biāo)對象的線程,當(dāng)其中一個線程享對于具有相同目標(biāo)對象的線程,當(dāng)其中一個線程享用用CPU資源時,目標(biāo)對象自動調(diào)用接口中的資源時,目標(biāo)對象自動調(diào)用接口中的run方法,方法,這時,這時,run方法中的局部變量被分配內(nèi)存空間,當(dāng)輪到方法中的局部變量被分配內(nèi)存空間,當(dāng)輪到另一個線程享用另一個線程享用CPU資源時,目標(biāo)對象會再次調(diào)用接口資源時,目標(biāo)對象會再次調(diào)用接口中的中的run方法,那么,方法,那么,run()方法中的局部變量會再次分方法中的局部變量會再次分配內(nèi)存空間。也就是說配內(nèi)存空間。也就是說run()run()方法已經(jīng)啟

15、動運行了兩次,方法已經(jīng)啟動運行了兩次,分別運行在不同的線程中,即運行在不同的時間片內(nèi)。分別運行在不同的線程中,即運行在不同的時間片內(nèi)。 第 16 頁12.4 線程的常用方法線程的常用方法 1start() : 線程調(diào)用該方法將啟動線程,使之從新建狀態(tài)進入就緒線程調(diào)用該方法將啟動線程,使之從新建狀態(tài)進入就緒隊列排隊,一旦輪到它來享用隊列排隊,一旦輪到它來享用CPUCPU資源時,就可以脫離創(chuàng)建它的線程獨立開資源時,就可以脫離創(chuàng)建它的線程獨立開始自己的生命周期了。始自己的生命周期了。 2run(): Thread類的類的run()方法與方法與Runnable接口中的接口中的run()方法的功能方法的

16、功能和作用相同,都用來定義線程對象被調(diào)度之后所執(zhí)行的操作,都是系統(tǒng)自和作用相同,都用來定義線程對象被調(diào)度之后所執(zhí)行的操作,都是系統(tǒng)自動調(diào)用而用戶程序不得引用的方法。動調(diào)用而用戶程序不得引用的方法。 3sleep(int millsecond): 優(yōu)先級高的線程可以在它的優(yōu)先級高的線程可以在它的run()方法中調(diào)方法中調(diào)用用sleep方法來使自己放棄方法來使自己放棄CPU資源,休眠一段時間。資源,休眠一段時間。 4isAlive(): 線程處于線程處于“新建新建”狀態(tài)時,線程調(diào)用狀態(tài)時,線程調(diào)用isAlive()方法返回方法返回false。在線程的在線程的run()方法結(jié)束之前,即沒有進入死亡狀

17、態(tài)之前,線程調(diào)用方法結(jié)束之前,即沒有進入死亡狀態(tài)之前,線程調(diào)用isAlive()方法返回方法返回true。 5currentThread():該方法是該方法是Thread類中的類方法,可以用類名調(diào)類中的類方法,可以用類名調(diào)用,該方法返回當(dāng)前正在使用用,該方法返回當(dāng)前正在使用CPU資源的線程。資源的線程。 6interrupt() :一個占有一個占有CPU資源的線程可以讓休眠的線程調(diào)用資源的線程可以讓休眠的線程調(diào)用interrupt()方法方法“吵醒吵醒”自己,即導(dǎo)致休眠的線程發(fā)生自己,即導(dǎo)致休眠的線程發(fā)生InterruptedException異常,從而結(jié)束休眠,重新排隊等待異常,從而結(jié)束休眠

18、,重新排隊等待CPU資源。資源。 第 17 頁例子例子5(Example12_5.java , Home.java )中一個線程每隔1秒鐘在命令行窗口輸出本地機器的時間,在3秒鐘后,該線程又被秒鐘后,該線程又被分配了實體分配了實體,新實體又開始運行。新實體又開始運行。因為垃圾實體仍然在工作垃圾實體仍然在工作,因此,在命令行每秒鐘能看見兩行同樣的本地機器時間.運行效果如圖12.7。 第 18 頁例子例子6(Example12_6.java , ClassRoom.java )中,有兩個線程:student和teacher,其中student準(zhǔn)備睡一小時后再開始上課,teacher在輸出3句“上課

19、”后,吵醒休眠的線程student。運行效果如圖12.8。 第 19 頁12.5 線程同步線程同步 在處理多線程問題時,我們必須注意這樣一個問題:當(dāng)兩個或多個線程同時訪問同一個變量,并且一個線程需要修改這個變量。我們應(yīng)對這樣的問題作出處理。 在處理線程同步時,要做的第一件事就是要把修改數(shù)據(jù)的方法用關(guān)鍵字用關(guān)鍵字synchronizedsynchronized來修飾。來修飾。 所謂線程同步所謂線程同步就是若干個線程都需要使用一個synchronized修飾的方法。例子例子7(7(Example12_7.javaExample12_7.java , , Bank.java Bank.java )

20、)中有兩個線程:會計和出納,他倆共同擁有一個帳本 .程序要保證其中一人使用saveOrTake(int amount)時,另一個人將必須等待,即saveOrTake(int amount)方法應(yīng)當(dāng)是一個synchronizedsynchronized方法方法。程序運行效果如圖12.9 . 第 20 頁12.6 協(xié)調(diào)同步的線程協(xié)調(diào)同步的線程 wait()wait()方法方法可以中斷方法的執(zhí)行,使本線程等待,暫時讓出可以中斷方法的執(zhí)行,使本線程等待,暫時讓出CPUCPU的使用的使用權(quán),并允許其它線程使用這個同步方法。權(quán),并允許其它線程使用這個同步方法。 notifyAll()notifyAll()

21、方法方法通知所有的由于使用這個同步方法而處于等待的線程結(jié)通知所有的由于使用這個同步方法而處于等待的線程結(jié)束等待。曾中斷的線程就會從剛才的中斷處繼續(xù)執(zhí)行這個同步方法,并遵束等待。曾中斷的線程就會從剛才的中斷處繼續(xù)執(zhí)行這個同步方法,并遵循循“先中斷先繼續(xù)先中斷先繼續(xù)”的原則。的原則。 notify()notify()方法方法只是通知處于等待中的線程的某一個結(jié)束等待。只是通知處于等待中的線程的某一個結(jié)束等待。 例子例子8(Example12_8.java, TicketHouse.java )模擬兩個人,模擬兩個人,張飛和李逵買電影票。售票員張飛和李逵買電影票。售票員只有只有兩張五元的錢兩張五元的錢

22、,電影票,電影票5元元錢一張。錢一張。張飛拿二十元一張的張飛拿二十元一張的人民幣人民幣排在李逵的前面買票,排在李逵的前面買票,李逵拿一張李逵拿一張5元的人民幣買票元的人民幣買票。因此因此張飛必須等待張飛必須等待(李逵比張(李逵比張飛先買了票)。程序運行效果飛先買了票)。程序運行效果如圖如圖12.10。 第 21 頁12.7 線程聯(lián)合線程聯(lián)合 一個線程A在占有CPU資源期間,可以讓其它線程調(diào)用join()和本線程聯(lián)合,如: B.join();B.join();稱A在運行期間聯(lián)合了B。如果線程A在占有CPU資源期間一旦聯(lián)合B線程,那么A線程將立刻中斷執(zhí)行,一直等到它聯(lián)合的線程B執(zhí)行完畢,A線程再重

23、新排隊等待CPU資源,以便恢復(fù)執(zhí)行。如果A準(zhǔn)備聯(lián)合的B線程已經(jīng)結(jié)束,那么B.join()不會產(chǎn)生任何效果。例子例子9(9(Example12_9.javaExample12_9.java , , ThreadJoin.javaThreadJoin.java ) )使用線程聯(lián)合模擬顧客等待蛋糕師制作蛋糕,程序運行效果如圖12.11 . 第 22 頁12.8 GUIGUI線程線程 當(dāng)Java程序包含圖形用戶界面(GUI)時,Java虛擬機在運行應(yīng)用程序時會自動啟動更多的線程,其中有兩個重要的線程:AWT-EventQuecueAWT-EventQuecue和AWT-WindowsAWT-Windo

24、ws。AWT-EventQuecue線程負責(zé)處理GUI事件,AWT-Windows線程負責(zé)將窗體或組件繪制到桌面。JVM要保證各個線程都有使用CPU資源的機會,比如,程序中發(fā)生GUI界面事件時,JVM就會將CPU資源切換給AWT-EventQuecue線程,AWT-EventQuecue線程就會來處理這個事件,比如,你單擊了程序中的按鈕,觸發(fā)ActionEvent事件,AWT-EventQuecue線程就立刻排隊等候執(zhí)行處理事件的代碼 第 23 頁例子例子10(Example12_10.java , WindowTyped.java )是訓(xùn)練用戶尋找鍵盤上的字母的快速能力。一個線程giveLe

25、tter負責(zé)每隔3秒給出一個英文字母,用戶需要在文本框中輸入這個英文字母,按回車確認。當(dāng)用戶按回車鍵時,將觸發(fā)ActionEvent事件,那么JVM就會中斷giveLetter線程,把CUP的使用權(quán)切換給WT-EventQuecue線程,以便處理ActionEvent事件。程序運行效果如圖12.12。第 24 頁 例子例子11(Example12_11.java , Win.java )中單擊start按扭線程開始工作:每隔一秒鐘顯示一次當(dāng)前時間;單擊stop按扭后,線程就結(jié)束了生命,釋放了實體,即釋放線程對象的內(nèi)存 .把一個線程委派給一個組件事件時要格外小心,比如單擊一個按扭讓線程開始運行,

26、那么當(dāng)這個線程在執(zhí)行完run()方法之前,客戶可 能 會 隨 時 再 次 單 擊 該 按 扭 , 這 時 就 會 發(fā) 生ILLegalThreadStateException 異常。程序運行效果如圖12.13 .第 25 頁 當(dāng)某些操作需要周期性地執(zhí)行,就可以使用計時器。我們可以使用Timer類的構(gòu)造方法:Timer(int a, Object b)創(chuàng)建一個計時器,其中的參數(shù)a的單位是豪秒,確定計時器每隔a 毫秒“震鈴”一次,參數(shù)參數(shù)b是計時器的監(jiān)視器是計時器的監(jiān)視器。計時器發(fā)生的震鈴事件發(fā)生的震鈴事件是ActinEvent類型事件。當(dāng)震鈴事件發(fā)生時,監(jiān)視器就會監(jiān) 視 到 這 個 事 件 , 監(jiān) 視 器 就 回 調(diào), 監(jiān) 視 器 就 回 調(diào) A c t i o n L i s t e n e r 接 口 中 的接 口 中 的actionPerformed(ActionEvent e)方法方法。使用Time

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論