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

下載本文檔

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

文檔簡介

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

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

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

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

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

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

7、)方法,其目的是規(guī)定線程的具體操作,否則線程就什么也不做,因為父類的run()方法中沒有任何操作語句。,2020/8/24,第 12 頁,12.3.2 使用Thread類,創(chuàng)建線程的另一個途徑就是用Thread類直接創(chuàng)建線程對象。使用Thread創(chuàng)建線程通常使用的構(gòu)造方法是: Thread(Runnable target) 該構(gòu)造方法中的參數(shù)是一個Runnable類型的接口。 在創(chuàng)建線程對象時必須向構(gòu)造方法的參數(shù)傳遞一個實現(xiàn)Runnable接口類的實例,該實例對象稱作所創(chuàng)線程的目標對象,當線程調(diào)用start()方法后,一旦輪到它來享用CPU資源,目標對象就會自動調(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的細微差別。,2020/8/24,第 13 頁,線程間可以共享相同的內(nèi)存單元(包括代碼與數(shù)據(jù)),并利用這些共享單元來實現(xiàn)數(shù)據(jù)交換、實時通信與必要的同步操作。,例子3(Example12_3.java , House.java )中使用Thread類創(chuàng)建兩個模擬貓和狗的線程,貓和狗共享房屋中的一桶水,即房屋是

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

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

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

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

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

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

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

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

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

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

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

溫馨提示

  • 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)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論