Java程序設(shè)計(jì)PPT課件版 第八章 多線程_第1頁
Java程序設(shè)計(jì)PPT課件版 第八章 多線程_第2頁
Java程序設(shè)計(jì)PPT課件版 第八章 多線程_第3頁
Java程序設(shè)計(jì)PPT課件版 第八章 多線程_第4頁
Java程序設(shè)計(jì)PPT課件版 第八章 多線程_第5頁
已閱讀5頁,還剩24頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第六章多線程授課教師:高成珍QQ:1281147324進(jìn)程和線程綜合示例線程的互斥和同步線程的狀態(tài)和生命周期創(chuàng)建線程的兩種方式本章主要內(nèi)容能夠自主實(shí)現(xiàn)多線程示例理解線程的互斥和同步熟練掌握創(chuàng)建線程的兩種方式

熟練掌握線程狀態(tài)間的轉(zhuǎn)化

本章重點(diǎn)與難點(diǎn)理解和掌握進(jìn)程和線程的概念進(jìn)程和線程幾乎所有的操作系統(tǒng)都支持同時(shí)運(yùn)行多個(gè)任務(wù),一個(gè)任務(wù)通常就是一個(gè)程序,每個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程(Process)。當(dāng)一個(gè)程序運(yùn)行時(shí),內(nèi)部可能包含了多個(gè)順序執(zhí)行流,每個(gè)順序執(zhí)行流就是一個(gè)線程(Thread)。進(jìn)程與線程的區(qū)別1、進(jìn)程擁有自己獨(dú)立的資源,線程不擁有資源,它與父進(jìn)程的其他線程共享該進(jìn)程所擁有的全部資源;2、創(chuàng)建或撤銷一個(gè)進(jìn)程所需要的開銷比創(chuàng)建或撤銷一個(gè)線程所需要的開銷大;3、進(jìn)程為重量級(jí)組件,線程為輕量級(jí)組件;任務(wù)1任務(wù)2任務(wù)3多線程在多個(gè)CPU上運(yùn)行多線程分享單個(gè)CPU任務(wù)1任務(wù)2任務(wù)3并行和并發(fā)

并行(Parallel)指在同一時(shí)刻,有多條指令在多個(gè)處理器上同時(shí)執(zhí)行;

并發(fā)(concurrency)指在同一時(shí)刻只能有一條指令執(zhí)行,但多個(gè)進(jìn)程指令被快速輪換執(zhí)行,使得宏觀上具有多個(gè)進(jìn)程同時(shí)執(zhí)行的效果。線程類介紹(Thread)

publicstaticThreadcurrentThread():返回當(dāng)前執(zhí)行的線程對(duì)象;publicfinalStringgetName():返回該線程的名稱;publicfinalvoidsetPriority(int

newPriority):更改線程的優(yōu)先級(jí)。publicThread.State

getState():返回該線程的狀態(tài)。publicvoidstart():使該線程開始執(zhí)行,多次啟動(dòng)一個(gè)線程是非法的;publicstaticvoidsleep(long

millis)throwsInterruptedException在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行)。publicstaticvoidyield():暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。構(gòu)造方法:Thread()、Thread(Stringname)、Thread(Runnabletarget)線程的創(chuàng)建和啟動(dòng)定義Thread類的子類,并重寫該類的run()方法,該run()方法的方法體就代表了線程需要完成的任務(wù);創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建線程對(duì)象;調(diào)用線程對(duì)象的start()方法啟動(dòng)該線程。1、繼承Thread類創(chuàng)建線程類

在Java中,程序入口被自動(dòng)創(chuàng)建為主線程,main()方法的方法體就是主線程的線程執(zhí)行體。

啟動(dòng)線程使用start()方法,而不是run()方法!如果直接調(diào)用run()方法,系統(tǒng)會(huì)把線程對(duì)象當(dāng)成一個(gè)普通對(duì)象,而run()方法也是一個(gè)普通方法,而不是線程執(zhí)行體。線程的創(chuàng)建和啟動(dòng)定義Runnable接口的實(shí)現(xiàn)類,并重寫該接口的run()方法,該run()方法的方法體即該線程的線程執(zhí)行體;創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為Thread的target來創(chuàng)建Thread對(duì)象,該Thread對(duì)象才是真正的線程對(duì)象;調(diào)用線程對(duì)象的start()方法啟動(dòng)該線程。2、實(shí)現(xiàn)Runnable接口創(chuàng)建線程第一種方式只能在類沒有繼承其它任何類的情況下才能使用?,如果一個(gè)類要繼承其它的類,最好選用第二種方法,這樣有更好的靈活性。線程的生命周期1、新建和就緒狀態(tài)當(dāng)程序使用new關(guān)鍵字創(chuàng)建一個(gè)線程之后,該線程就處于新建狀態(tài),此時(shí)它和其他的Java對(duì)象一樣,僅僅由Java虛擬機(jī)為其分配內(nèi)存,并初始化其成員變量的值。當(dāng)調(diào)用線程對(duì)象的start()方法之后,該線程就處于就緒狀態(tài),處于這個(gè)狀態(tài)中的線程并沒有開始運(yùn)行,只是表示該線程可以運(yùn)行了。至于該線程何時(shí)開始運(yùn)行,取決于JVM里線程調(diào)度器的調(diào)度。在線程的生命周期中,要經(jīng)過新建(New)、就緒(Runnable)、運(yùn)行(Running)、阻塞(Blocked)和死亡(Dead)5種狀態(tài)。線程啟動(dòng)以后,不可能一直霸占著CPU獨(dú)自運(yùn)行,CPU需要在多條線程之間切換,于是線程狀態(tài)也會(huì)多次在運(yùn)行、阻塞之間切換。線程的生命周期2、運(yùn)行和阻塞狀態(tài)如果處于就緒狀態(tài)的線程獲得了CPU,開始執(zhí)行run()方法,則該線程處于運(yùn)行狀態(tài),線程在運(yùn)行過程中會(huì)被中斷,目的是使其他線程獲得執(zhí)行的機(jī)會(huì),線程調(diào)度的細(xì)節(jié)取決于底層平臺(tái)所采用的策略。當(dāng)發(fā)生如下情況時(shí),線程會(huì)進(jìn)入阻塞狀態(tài)線程調(diào)用sleep()方法主動(dòng)放棄所占用的處理器資源;線程調(diào)用一個(gè)阻塞式IO方法,在該方法返回之前,該線程被阻塞;線程試圖獲得一個(gè)同步監(jiān)視器,但該同步監(jiān)視器正被其他線程所持有;線程在等待某個(gè)通知(notify);線程的生命周期被阻塞的線程會(huì)在合適的時(shí)候重新進(jìn)入就緒狀態(tài),注意不是運(yùn)行狀態(tài)。被阻塞線程的阻塞解除后,必須重新等待線程調(diào)度器再次調(diào)度它。當(dāng)發(fā)生如下情況時(shí),可解除阻塞,讓線程重新進(jìn)入就緒狀態(tài)。調(diào)用sleep()方法的線程經(jīng)過了指定時(shí)間;線程調(diào)用的阻塞式IO方法已經(jīng)返回;線程成功地獲得了試圖取得的同步監(jiān)視器;線程正在等待某個(gè)通知時(shí),其他線程發(fā)出了一個(gè)通知;2、運(yùn)行和阻塞狀態(tài)線程的生命周期run()方法執(zhí)行完成,線程正常結(jié)束;線程拋出一個(gè)未捕獲的Exception或Error;直接調(diào)用該線程的stop()方法來結(jié)束該線程。注意:當(dāng)主線程結(jié)束時(shí),其他線程不受任何影響,并不會(huì)隨之結(jié)束。一旦子線程啟動(dòng)起來后,它就擁有和主線程相同的地位。3、線程死亡為了測(cè)試某個(gè)線程是否已經(jīng)死亡,可以調(diào)用線程對(duì)象的isAlive()方法,當(dāng)線程處于就緒、運(yùn)行、阻塞3種狀態(tài)時(shí),該方法將返回true;當(dāng)線程處于新建、死亡2中狀態(tài)時(shí),該方法將返回false。線程狀態(tài)轉(zhuǎn)換圖線程狀態(tài)轉(zhuǎn)換圖控制線程如果需要當(dāng)前正在執(zhí)行的線程暫停一段時(shí)間,并進(jìn)入阻塞狀態(tài),可通過調(diào)用Thread類的靜態(tài)方法sleep()方法來實(shí)現(xiàn)。即使系統(tǒng)中沒有其他可執(zhí)行的線程,處于sleep()中的線程也不會(huì)執(zhí)行,sleep()方法常用來暫停程序的執(zhí)行。1、線程睡眠(sleep)

Thread提供了讓一個(gè)線程等待另一個(gè)線程完成的方法—join()方法。當(dāng)在某個(gè)程序執(zhí)行流中調(diào)用其他線程的join()方法時(shí),調(diào)用線程將被阻塞,直到被join()方法join線程執(zhí)行完為止。2、join線程控制線程有一種線程,它是在后臺(tái)運(yùn)行的,它的任務(wù)是為其他的線程提供服務(wù),這種線程被稱為“后臺(tái)線程”,也叫“守護(hù)線程”或“精靈線程”。JVM的垃圾回收線程就是典型的后臺(tái)線程。后臺(tái)線程有個(gè)特征:如果所有的前臺(tái)線程都死亡,后臺(tái)線程會(huì)自動(dòng)死亡。3、后臺(tái)線程(Daemon)調(diào)用Thread對(duì)象的setDaemon(true)方法可將指定線程設(shè)置為后臺(tái)線程,通過isDaemon()方法,可判斷指定線程是否為后臺(tái)線程。當(dāng)要將某個(gè)線程設(shè)置為后臺(tái)線程時(shí),必須要在該線程啟動(dòng)之前,否則會(huì)引發(fā)IllegalThreadStateException異常??刂凭€程

yield()方法和sleep()方法相似,它也可以讓當(dāng)前正在執(zhí)行的線程暫停,但它不會(huì)阻塞該線程,它只是將該線程轉(zhuǎn)入就緒狀態(tài)。即讓系統(tǒng)的線程調(diào)度器重新調(diào)度一次。完全可能的情況是:當(dāng)某個(gè)線程調(diào)用了yield()方法暫停之后,線程調(diào)度器又將其調(diào)度出來重新執(zhí)行。4、線程讓步(yield)當(dāng)某個(gè)線程調(diào)用了yield()方法暫停之后,只有優(yōu)先級(jí)與當(dāng)前線程相同,或者優(yōu)先級(jí)比當(dāng)前線程更高的處于就緒狀態(tài)的線程才會(huì)獲得執(zhí)行的機(jī)會(huì)??刂凭€程

sleep()方法和yield()方法的區(qū)別:sleep()方法暫停當(dāng)前線程后,會(huì)給其他線程執(zhí)行機(jī)會(huì),不會(huì)理會(huì)其他線程的優(yōu)先級(jí);但yield()方法只會(huì)給優(yōu)先級(jí)相同,或優(yōu)先級(jí)更高的線程執(zhí)行機(jī)會(huì);sleep()方法會(huì)將線程轉(zhuǎn)入阻塞狀態(tài),直到經(jīng)過阻塞時(shí)間才會(huì)轉(zhuǎn)入就緒狀態(tài);而yield()不會(huì)將線程轉(zhuǎn)入阻塞狀態(tài),它只是強(qiáng)制當(dāng)前線程進(jìn)入就緒狀態(tài);sleep()方法聲明拋出了InterruptedException異常,所以調(diào)用sleep()方法時(shí)要慢捕捉該異常,要么顯示聲明拋出該異常;而yield()方法則沒有聲明拋出任何異常;模擬賬戶存取錢

銀行賬戶類,提供相關(guān)屬性的setter和getter方法操作線程類的構(gòu)造方法,傳入需要操作的賬戶、具體的操作以及操作的金額模擬賬戶存取錢線程執(zhí)行體測(cè)試方法模擬賬戶存取錢多線程操作時(shí),會(huì)存在余額為負(fù)數(shù)的情況,為什么會(huì)這樣,如何解決?線程同步為了解決多個(gè)線程對(duì)共享資源的操作而導(dǎo)致的數(shù)據(jù)不一致問題,Java的多線程支持引入了同步監(jiān)視器,使用關(guān)鍵字synchronized。線程開始執(zhí)行同步代碼塊之前,必須先獲得對(duì)同步監(jiān)視器的鎖定。通用方法就是同步代碼塊,語法格式如下:synchronized(obj){ … //此處的代碼就是同步代碼塊}注意:任何時(shí)刻只能有一個(gè)線程可以獲得對(duì)同步監(jiān)視器的鎖定,當(dāng)同步代碼塊執(zhí)行完成后,該線程會(huì)釋放對(duì)該同步監(jiān)視器的鎖定。同步方法同步方法與同步代碼塊相似,需要使用synchronized關(guān)鍵字修飾,對(duì)于同步方法而言,無須顯示指定同步監(jiān)視器,同步方法的同步監(jiān)視器是this,即當(dāng)前對(duì)象本身。通過使用同步方法可方便實(shí)現(xiàn)線程安全的類,線程安全的類具有如下特征:該類的對(duì)象可以被多個(gè)線程安全地訪問;每個(gè)線程調(diào)用該對(duì)象的任意方法后都將得到正確結(jié)果;每個(gè)線程調(diào)用該對(duì)象的任意方法后,該對(duì)象狀態(tài)依然保持合理狀態(tài)。

不可變類總是線程安全的,因?yàn)樗膶?duì)象狀態(tài)不可改變;但可變對(duì)象需要額外的方法(同步方法)來保證線程安全,這是以降低程序的運(yùn)行效率為代價(jià)的。通常只對(duì)那些會(huì)改變共享資源的方法進(jìn)行同步。釋放同步監(jiān)視器任何線程進(jìn)入同步代碼塊、同步方法之前,必須先獲得對(duì)同步監(jiān)視器的鎖定,那么何時(shí)會(huì)釋放對(duì)同步監(jiān)視器的鎖定呢?當(dāng)前線程的同步方法、同步代碼塊執(zhí)行結(jié)束,即釋放同步監(jiān)視器;當(dāng)前線程在同步方法、同步代碼塊中遇到break、return終止了該代碼塊、該方法的繼續(xù)執(zhí)行,將會(huì)釋放同步監(jiān)視器;當(dāng)前線程在同步方法、同步代碼塊中出現(xiàn)了未處理的Error或Exception,導(dǎo)致代碼塊或方法異常結(jié)束時(shí),會(huì)釋放同步監(jiān)視器;當(dāng)前線程執(zhí)行同步代碼塊或同步方式時(shí),程序執(zhí)行了同步監(jiān)視器對(duì)象的wait()方法,則當(dāng)前線程暫停,并釋放同步監(jiān)視器。注意:當(dāng)同步代碼塊或同步方法中,調(diào)用Thread.sleep()、Thread.yield()方法來暫停當(dāng)前線程的執(zhí)行,當(dāng)前線程不會(huì)釋放同監(jiān)視器。同步監(jiān)視器引起的死鎖問題

Java線程死鎖是一個(gè)經(jīng)典的多線程問題,是指兩個(gè)或兩個(gè)以上的線程在執(zhí)行過程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。導(dǎo)致死鎖必須滿足以下條件:互斥,即多個(gè)線程不能同時(shí)使用同一資源;占有等待,即某個(gè)線程必須同時(shí)擁有幾個(gè)資源才能執(zhí)行完成;非剝奪,即資源只能由線程執(zhí)行完主動(dòng)釋放,而不能在別的線程沒有釋放資源的情況下,奪走其已占有的資源;環(huán)路等待條件:你等待我釋放資源,我等待你釋放資源,資源沒有滿足的線程無限期地等待。例如有兩個(gè)人A和B,面前擺放著食物,需要同時(shí)使用刀和叉才能食用,但現(xiàn)在只有一副刀叉,A獲得了刀,B獲得了叉。A在等待獲得叉,B在等待獲得刀。誰也不愿意給對(duì)方,這時(shí)候就進(jìn)入僵持狀態(tài)即死鎖狀態(tài)。模擬死鎖的關(guān)鍵代碼程序執(zhí)行入口,主方法線程方法執(zhí)行體生產(chǎn)者消費(fèi)者問題解決方案:讓生產(chǎn)者在緩沖區(qū)滿時(shí)休眠,等到下次消費(fèi)者消耗緩沖區(qū)中的數(shù)據(jù)時(shí),生產(chǎn)者才能被喚醒,開始往緩沖區(qū)添加數(shù)據(jù)。同樣,讓消費(fèi)者在緩沖區(qū)空時(shí)進(jìn)入休眠,等到生產(chǎn)者往緩沖區(qū)添加數(shù)據(jù)后,再喚醒消費(fèi)者。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(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ǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論