Java2實(shí)用教程第4版第12章Java多線程機(jī)制.ppt_第1頁
Java2實(shí)用教程第4版第12章Java多線程機(jī)制.ppt_第2頁
Java2實(shí)用教程第4版第12章Java多線程機(jī)制.ppt_第3頁
Java2實(shí)用教程第4版第12章Java多線程機(jī)制.ppt_第4頁
Java2實(shí)用教程第4版第12章Java多線程機(jī)制.ppt_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

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

2、過程也是進(jìn)程本身從產(chǎn)生、發(fā)展至消亡的過程。 現(xiàn)代操作系統(tǒng)可以同時(shí)管理一個(gè)計(jì)算機(jī)系統(tǒng)中的多個(gè)進(jìn)程,即可以讓計(jì)算機(jī)系統(tǒng)中的多個(gè)進(jìn)程輪流使用CPU資源。,2020/8/24,第 5 頁,12.1.2 進(jìn)程與線程,線程是比進(jìn)程更小的執(zhí)行單位,一個(gè)進(jìn)程在其執(zhí)行過程中,可以產(chǎn)生多個(gè)線程,形成多條執(zhí)行線索,每條線索,即每個(gè)線程也有它自身的產(chǎn)生、存在和消亡的過程。 線程間可以共享進(jìn)程中的某些內(nèi)存單元(包括代碼與數(shù)據(jù)),線程的中斷與恢復(fù)可以更加節(jié)省系統(tǒng)的開銷。,2020/8/24,第 6 頁,12.2 Java中的線程 12.2.1 Java的多線程機(jī)制,Java語言的一大特性點(diǎn)就是內(nèi)置對多線程的支持。 Jav

3、a虛擬機(jī)快速地把控制從一個(gè)線程切換到另一個(gè)線程。這些線程將被輪流執(zhí)行,使得每個(gè)線程都有機(jī)會(huì)使用CPU資源。,2020/8/24,第 7 頁,12.2.2 主線程(main線程),每個(gè)Java應(yīng)用程序都有一個(gè)缺省的主線程。 當(dāng)JVM(Java Virtual Machine 虛擬機(jī))加載代碼,發(fā)現(xiàn)main方法之后,就會(huì)啟動(dòng)一個(gè)線程,這個(gè)線程稱為“主線程”(main線程),該線程負(fù)責(zé)執(zhí)行main方法。 JVM一直要等到Java應(yīng)用程序中的所有線程都結(jié)束之后,才結(jié)束Java應(yīng)用程序 。,2020/8/24,第 8 頁,12.2.3 線程的狀態(tài)與生命周期,建的線程在它的一個(gè)完整的生命周期中通常要經(jīng)歷如

4、下的四種狀態(tài): 1新建: 當(dāng)一個(gè)Thread類或其子類的對象被聲明并創(chuàng)建時(shí),新生的線程對象處于新建狀態(tài)。 2運(yùn)行 :線程必須調(diào)用start()方法(從父類繼承的方法)通知JVM,這樣JVM就會(huì)知道又有一個(gè)新一個(gè)線程排隊(duì)等候切換了。一旦輪到它來享用CPU資源時(shí),此線程的就可以脫離創(chuàng)建它的主線程獨(dú)立開始自己的生命周期了。 3中斷:有4種原因的中斷: JVM將CPU資源從當(dāng)前線程切換給其他線程,使本線程讓出CPU的使用權(quán)處于中斷狀態(tài)。 線程使用CPU資源期間,執(zhí)行了sleep(int millsecond)方法,使當(dāng)前線程進(jìn)入休眠狀。 線程使用CPU資源期間,執(zhí)行了wait()方法。 線程使用CPU

5、資源期間,執(zhí)行某個(gè)操作進(jìn)入阻塞狀態(tài)。 4死亡 :處于死亡狀態(tài)的線程不具有繼續(xù)運(yùn)行的能力。線程釋放了實(shí)體。,2020/8/24,第 9 頁,例子1(Example12_1.java )通過分析運(yùn)行結(jié)果闡述線程的4種狀態(tài)。例子1在主線程中用Thread的子類創(chuàng)建了兩個(gè)線程(SpeakElephant.java , SpeakCar.java ),這兩個(gè)線程分別在命令行窗口輸出20句“大象”和“轎車”;主線程在命令行窗口輸出15句“主人”。 例子1的運(yùn)行效果如圖12.4。 例子1在不同的計(jì)算機(jī)運(yùn)行或在同一臺(tái)計(jì)算機(jī)反復(fù)運(yùn)行的結(jié)果不盡相同,輸出結(jié)果依賴當(dāng)前CPU資源的使用情況。,2020/8/24,第

6、10 頁,12.2.4 線程調(diào)度與優(yōu)先級,處于就緒狀態(tài)的線程首先進(jìn)入就緒隊(duì)列排隊(duì)等候CPU資源,同一時(shí)刻在就緒隊(duì)列中的線程可能有多個(gè)。Java虛擬機(jī)(JVM)中的線程調(diào)度器負(fù)責(zé)管理線程,調(diào)度器把線程的優(yōu)先級分為10個(gè)級別,分別用Thread類中的類常量表示。 Java調(diào)度器的任務(wù)是使高優(yōu)先級的線程能始終運(yùn)行,一旦時(shí)間片有空閑,則使具有同等優(yōu)先級的線程以輪流的方式順序使用時(shí)間片。,2020/8/24,第 11 頁,12.3 Thread類與線程的創(chuàng)建 12.3.1 使用Thread的子類,在Java語言中,用Thread類或子類創(chuàng)建線程對象。 在編寫Thread類的子類時(shí),需要重寫父類的run(

7、)方法,其目的是規(guī)定線程的具體操作,否則線程就什么也不做,因?yàn)楦割惖膔un()方法中沒有任何操作語句。,2020/8/24,第 12 頁,12.3.2 使用Thread類,創(chuàng)建線程的另一個(gè)途徑就是用Thread類直接創(chuàng)建線程對象。使用Thread創(chuàng)建線程通常使用的構(gòu)造方法是: Thread(Runnable target) 該構(gòu)造方法中的參數(shù)是一個(gè)Runnable類型的接口。 在創(chuàng)建線程對象時(shí)必須向構(gòu)造方法的參數(shù)傳遞一個(gè)實(shí)現(xiàn)Runnable接口類的實(shí)例,該實(shí)例對象稱作所創(chuàng)線程的目標(biāo)對象,當(dāng)線程調(diào)用start()方法后,一旦輪到它來享用CPU資源,目標(biāo)對象就會(huì)自動(dòng)調(diào)用接口中的run()方法(接口

8、回調(diào))。 例子2 (Example12_2.java, ElephantTarget.java , CarTarget.java )和前面的例子1不同,不使用Thread類的子類創(chuàng)建線程,而是使用Thread類創(chuàng)建speakElephant和speakCar線程,請讀者注意比較例子1和例子2的細(xì)微差別。,2020/8/24,第 13 頁,線程間可以共享相同的內(nèi)存單元(包括代碼與數(shù)據(jù)),并利用這些共享單元來實(shí)現(xiàn)數(shù)據(jù)交換、實(shí)時(shí)通信與必要的同步操作。,例子3(Example12_3.java , House.java )中使用Thread類創(chuàng)建兩個(gè)模擬貓和狗的線程,貓和狗共享房屋中的一桶水,即房屋是

9、線程的目標(biāo)對象,房屋中的一桶水被貓和狗共享。貓和狗輪流喝水(狗喝的多,貓喝的少),當(dāng)水被喝盡時(shí),貓和狗進(jìn)入死亡狀態(tài)。貓或狗在輪流喝水的過程中,主動(dòng)休息片刻(讓Thread類調(diào)用sleep(int n)進(jìn)入中斷狀態(tài)),而不是等到被強(qiáng)制中斷喝水。,2020/8/24,第 14 頁,12.3.3 目標(biāo)對象與線程的關(guān)系,從對象和對象之間的關(guān)系角度上看,目標(biāo)對象和線程的關(guān)系有以下兩種情景。 1.目標(biāo)對象和線程完全解耦 目標(biāo)對象沒有組合線程對象.目標(biāo)對象經(jīng)常需要通過獲得線程的名字(因?yàn)闊o法獲得線程對象的引用)以便確定是哪個(gè)線程正在占用CPU資源,即被JVM正在執(zhí)行的線程。 2.目標(biāo)對象組合線程(弱耦合)

10、目標(biāo)對象可以組合線程.目標(biāo)對象類組合線程對象時(shí), 目標(biāo)對象可以通過獲得線程對象的引用.,例子4中(Example12_4.java , House.java ),線程cat和dog在House中,請注意例子4與例子3的區(qū)別 .,2020/8/24,第 15 頁,12.3.4 關(guān)于run()方法啟動(dòng)的次數(shù),對于具有相同目標(biāo)對象的線程,當(dāng)其中一個(gè)線程享用CPU資源時(shí),目標(biāo)對象自動(dòng)調(diào)用接口中的run方法,這時(shí),run方法中的局部變量被分配內(nèi)存空間,當(dāng)輪到另一個(gè)線程享用CPU資源時(shí),目標(biāo)對象會(huì)再次調(diào)用接口中的run方法,那么,run()方法中的局部變量會(huì)再次分配內(nèi)存空間。也就是說run()方法已經(jīng)啟動(dòng)

11、運(yùn)行了兩次,分別運(yùn)行在不同的線程中,即運(yùn)行在不同的時(shí)間片內(nèi)。,2020/8/24,第 16 頁,12.4 線程的常用方法,1start() : 線程調(diào)用該方法將啟動(dòng)線程,使之從新建狀態(tài)進(jìn)入就緒隊(duì)列排隊(duì),一旦輪到它來享用CPU資源時(shí),就可以脫離創(chuàng)建它的線程獨(dú)立開始自己的生命周期了。 2run(): Thread類的run()方法與Runnable接口中的run()方法的功能和作用相同,都用來定義線程對象被調(diào)度之后所執(zhí)行的操作,都是系統(tǒng)自動(dòng)調(diào)用而用戶程序不得引用的方法。 3sleep(int millsecond): 優(yōu)先級高的線程可以在它的run()方法中調(diào)用sleep方法來使自己放棄CPU資源

12、,休眠一段時(shí)間。 4isAlive(): 線程處于“新建”狀態(tài)時(shí),線程調(diào)用isAlive()方法返回false。在線程的run()方法結(jié)束之前,即沒有進(jìn)入死亡狀態(tài)之前,線程調(diào)用isAlive()方法返回true。 5currentThread():該方法是Thread類中的類方法,可以用類名調(diào)用,該方法返回當(dāng)前正在使用CPU資源的線程。 6interrupt() :一個(gè)占有CPU資源的線程可以讓休眠的線程調(diào)用interrupt()方法“吵醒”自己,即導(dǎo)致休眠的線程發(fā)生InterruptedException異常,從而結(jié)束休眠,重新排隊(duì)等待CPU資源。,2020/8/24,第 17 頁,例子5(

13、Example12_5.java , Home.java )中一個(gè)線程每隔1秒鐘在命令行窗口輸出本地機(jī)器的時(shí)間,在3秒鐘后,該線程又被分配了實(shí)體,新實(shí)體又開始運(yùn)行。因?yàn)槔鴮?shí)體仍然在工作,因此,在命令行每秒鐘能看見兩行同樣的本地機(jī)器時(shí)間.運(yùn)行效果如圖12.7。,2020/8/24,第 18 頁,例子6(Example12_6.java , ClassRoom.java )中,有兩個(gè)線程:student和teacher,其中student準(zhǔn)備睡一小時(shí)后再開始上課,teacher在輸出3句“上課”后,吵醒休眠的線程student。運(yùn)行效果如圖12.8。,2020/8/24,第 19 頁,12.5

14、線程同步,在處理多線程問題時(shí),我們必須注意這樣一個(gè)問題:當(dāng)兩個(gè)或多個(gè)線程同時(shí)訪問同一個(gè)變量,并且一個(gè)線程需要修改這個(gè)變量。我們應(yīng)對這樣的問題作出處理。 在處理線程同步時(shí),要做的第一件事就是要把修改數(shù)據(jù)的方法用關(guān)鍵字synchronized來修飾。 所謂線程同步就是若干個(gè)線程都需要使用一個(gè)synchronized修飾的方法。 例子7(Example12_7.java , Bank.java )中有兩個(gè)線程:會(huì)計(jì)和出納,他倆共同擁有一個(gè)帳本 .程序要保證其中一人使用saveOrTake(int amount)時(shí),另一個(gè)人將必須等待,即saveOrTake(int amount)方法應(yīng)當(dāng)是一個(gè)syn

15、chronized方法。程序運(yùn)行效果如圖12.9 .,2020/8/24,第 20 頁,12.6 協(xié)調(diào)同步的線程,wait()方法可以中斷方法的執(zhí)行,使本線程等待,暫時(shí)讓出CPU的使用權(quán),并允許其它線程使用這個(gè)同步方法。 notifyAll()方法通知所有的由于使用這個(gè)同步方法而處于等待的線程結(jié)束等待。曾中斷的線程就會(huì)從剛才的中斷處繼續(xù)執(zhí)行這個(gè)同步方法,并遵循“先中斷先繼續(xù)”的原則。 notify()方法只是通知處于等待中的線程的某一個(gè)結(jié)束等待。,例子8(Example12_8.java, TicketHouse.java )模擬兩個(gè)人,張飛和李逵買電影票。售票員只有兩張五元的錢,電影票5元錢

16、一張。張飛拿二十元一張的人民幣排在李逵的前面買票,李逵拿一張5元的人民幣買票。因此張飛必須等待(李逵比張飛先買了票)。程序運(yùn)行效果如圖12.10。,2020/8/24,第 21 頁,12.7 線程聯(lián)合,一個(gè)線程A在占有CPU資源期間,可以讓其它線程調(diào)用join()和本線程聯(lián)合,如: B.join(); 稱A在運(yùn)行期間聯(lián)合了B。如果線程A在占有CPU資源期間一旦聯(lián)合B線程,那么A線程將立刻中斷執(zhí)行,一直等到它聯(lián)合的線程B執(zhí)行完畢,A線程再重新排隊(duì)等待CPU資源,以便恢復(fù)執(zhí)行。如果A準(zhǔn)備聯(lián)合的B線程已經(jīng)結(jié)束,那么B.join()不會(huì)產(chǎn)生任何效果。 例子9(Example12_9.java , Th

17、readJoin.java )使用線程聯(lián)合模擬顧客等待蛋糕師制作蛋糕,程序運(yùn)行效果如圖12.11 .,2020/8/24,第 22 頁,12.8 GUI線程,當(dāng)Java程序包含圖形用戶界面(GUI)時(shí),Java虛擬機(jī)在運(yùn)行應(yīng)用程序時(shí)會(huì)自動(dòng)啟動(dòng)更多的線程,其中有兩個(gè)重要的線程:AWT-EventQuecue和AWT-Windows。AWT-EventQuecue線程負(fù)責(zé)處理GUI事件,AWT-Windows線程負(fù)責(zé)將窗體或組件繪制到桌面。JVM要保證各個(gè)線程都有使用CPU資源的機(jī)會(huì),比如,程序中發(fā)生GUI界面事件時(shí),JVM就會(huì)將CPU資源切換給AWT-EventQuecue線程,AWT-Even

18、tQuecue線程就會(huì)來處理這個(gè)事件,比如,你單擊了程序中的按鈕,觸發(fā)ActionEvent事件,AWT-EventQuecue線程就立刻排隊(duì)等候執(zhí)行處理事件的代碼,2020/8/24,第 23 頁,例子10(Example12_10.java , WindowTyped.java )是訓(xùn)練用戶尋找鍵盤上的字母的快速能力。一個(gè)線程giveLetter負(fù)責(zé)每隔3秒給出一個(gè)英文字母,用戶需要在文本框中輸入這個(gè)英文字母,按回車確認(rèn)。當(dāng)用戶按回車鍵時(shí),將觸發(fā)ActionEvent事件,那么JVM就會(huì)中斷giveLetter線程,把CUP的使用權(quán)切換給WT-EventQuecue線程,以便處理Actio

19、nEvent事件。程序運(yùn)行效果如圖12.12。,2020/8/24,第 24 頁,例子11(Example12_11.java , Win.java )中單擊start按扭線程開始工作:每隔一秒鐘顯示一次當(dāng)前時(shí)間;單擊stop按扭后,線程就結(jié)束了生命,釋放了實(shí)體,即釋放線程對象的內(nèi)存 .把一個(gè)線程委派給一個(gè)組件事件時(shí)要格外小心,比如單擊一個(gè)按扭讓線程開始運(yùn)行,那么當(dāng)這個(gè)線程在執(zhí)行完run()方法之前,客戶可能會(huì)隨時(shí)再次單擊該按扭,這時(shí)就會(huì)發(fā)生ILLegalThreadStateException 異常。程序運(yùn)行效果如圖12.13 .,2020/8/24,第 25 頁,當(dāng)某些操作需要周期性地執(zhí)行,就可以使用計(jì)時(shí)器。我們可以使用Timer類的構(gòu)造方法:Timer(int a, Object b)創(chuàng)建一個(gè)計(jì)時(shí)器,其中的參數(shù)a的單位是豪秒,確定計(jì)時(shí)器每隔a 毫秒“震鈴”一次,參數(shù)b是計(jì)時(shí)器的監(jiān)視器。計(jì)時(shí)器發(fā)生的震鈴事件是ActinEvent類型事件。當(dāng)震鈴事件發(fā)生時(shí),監(jiān)視器就會(huì)監(jiān)視到這個(gè)事件,監(jiān)視器就回調(diào)ActionListener接口中的actionPerformed(ActionEvent e)方法。使用Timer類的方法start()啟動(dòng)計(jì)時(shí)器,即啟動(dòng)線程。使用Timer類的

溫馨提示

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

最新文檔

評論

0/150

提交評論