第9章 多線程-Java中_第1頁
第9章 多線程-Java中_第2頁
第9章 多線程-Java中_第3頁
第9章 多線程-Java中_第4頁
第9章 多線程-Java中_第5頁
已閱讀5頁,還剩25頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第9章多線程——Java中的并發(fā)協(xié)作隨著多核CPU的問世,使得多線程程序在開發(fā)中占有了更重要的位置,多線程編程技術(shù)已經(jīng)成為開發(fā)人員必不可少的一項重要技能。Java是原生就支持多線程編程的開發(fā)語言,用其進行多線程開發(fā)既方便又高效,本章將介紹Java中多線程開發(fā)的相關(guān)知識,主要包括線程的基本使用、狀態(tài)、調(diào)度、同步等方面。9.1線程的基本知識本節(jié)將介紹關(guān)于多線程開發(fā)的一些基本知識,包括什么是線程,如何定義、創(chuàng)建、啟動線程。只有掌握了這些基本知識,才能繼續(xù)學(xué)習(xí)更高級、更復(fù)雜的多線程開發(fā)。9.1.1多線程編程的意義多線程編程可以使程序具有兩條或兩條以上的并發(fā)執(zhí)行線索,就像日常工作中由多人同時合作完成一個任務(wù)。這在很多情況下可以改善程序的響應(yīng)性能,提高資源的利用效率,在多核CPU年代,這顯得尤為重要。然而濫用多線程也有可能給程序帶來意想不到的錯誤,降低程序執(zhí)行的效率。例如,開發(fā)一個網(wǎng)上購物時自動郵件通知的程序,在單擊提交按鈕確認定單時,一方面要顯示信息提示定單已確認,一方面應(yīng)該自動給用戶發(fā)送一份電子郵件。如果是單線程模式,則需要等待郵件發(fā)送完成之后,再顯示提示信息,由于郵件發(fā)送的過程相對較慢,可能要經(jīng)過漫長的等待才看到確認信息,界面響應(yīng)性能不是很好。而顯示定單確認信息與發(fā)送通知郵件這兩個工作是沒有相互約束關(guān)系的,完全可以一邊顯示提示信息,一邊發(fā)送通知郵件,這樣界面的響應(yīng)性能會提高很多,不用進行漫長的等待。9.1.1多線程編程的意義9.1.2定義自己的線程Java中的線程有兩方面的含義,一是一條獨立的執(zhí)行線索,二是java.lang.Thread類或其子類的對象。在Java中開發(fā)自己的線程有兩種方式,包括繼承Thread類與實現(xiàn)Runnable接口,這兩種方式在不同的場合各有優(yōu)缺點,本小節(jié)將對這兩種方式進行詳細的介紹。1.繼承Thread類2.實現(xiàn)Runnable接口3.兩種方式的比較9.1.3創(chuàng)建線程對象上一小節(jié)介紹了如何編寫描述線程任務(wù)的方法,本小節(jié)將介紹如何創(chuàng)建線程對象。對于繼承Thread類與實現(xiàn)Runnable接口兩種不同方式來說,在創(chuàng)建線程對象這一步是有區(qū)別的,下邊將分別介紹在這兩種情況下如何創(chuàng)建線程對象。1.繼承Thread類方式2.實現(xiàn)Runnable接口方式9.1.4啟動線程當(dāng)線程對象創(chuàng)建完成后,其還只是一個普通的對象,并沒有成為一條獨立的執(zhí)行線索。想讓其成為獨立的執(zhí)行線索必須進行啟動,在沒有啟動的情況下,開發(fā)人員可以像調(diào)用其他對象的方法一樣調(diào)用線程對象中的任何可見方法。下面的例子說明了這個問題,代碼如下。1 //創(chuàng)建Runnable實現(xiàn)類的對象2 MyRunnable

mr=newMyRunnable();3 //創(chuàng)建Thread對象4 Threadt=newThread(mr);5 //調(diào)用Thread對象中run方法6 t.run();9.1.4啟動線程9.1.5同時使用多個線程上一小節(jié)最后提到,兩條執(zhí)行線索并發(fā)運行時,結(jié)果可能是不唯一的。這是因為,如果有多個沒有同步約束關(guān)系的線程需要執(zhí)行,調(diào)度線程將不能保證哪個線程先執(zhí)行及其持續(xù)的時間,在不同的平臺上,或在同一平臺上多次運行可能會得到不同的結(jié)果。Java中對于線程啟動后唯一能夠保障的就是:“每個線程都將啟動,每個線程都會執(zhí)行結(jié)束”。但誰會先執(zhí)行誰會后執(zhí)行,將沒有保障,也就是說,就算一個線程在另一個線程之前啟動,也無法保障該線程一定在另一個線程之前執(zhí)行完畢。9.1.5同時使用多個線程9.2線程的狀態(tài)前面章節(jié)對線程的基本編程進行了簡單的介紹,本節(jié)將對線程的生命周期進行詳細的討論。線程對象自其被創(chuàng)建后,一般會經(jīng)歷生命周期中五種不同的狀態(tài)。9.3線程的調(diào)度前面已經(jīng)介紹了,Java自動調(diào)度沒有邏輯約束的線程時,其執(zhí)行順序是沒有保障的。但是可以通過編程調(diào)用一些調(diào)度線程的方法,來實現(xiàn)一定程度上對線程的調(diào)度。但要注意的是,這些調(diào)度線程的方法,有些是有保障的,有些只是影響線程進入執(zhí)行狀態(tài)的幾率。本節(jié)將介紹幾個簡單的線程調(diào)度的方法,下一節(jié)將會介紹比較復(fù)雜的線程的同步與調(diào)度。9.3.1睡眠在線程執(zhí)行的過程中,調(diào)用sleep方法可以讓線程睡眠一段指定的時間,等指定時間到達后,該線程則會蘇醒,并進入準(zhǔn)備狀態(tài)等待執(zhí)行。這是使正在執(zhí)行的線程讓出CPU的最簡單方法之一,其方法簽名如下。publicstaticvoidsleep(long

millis)throws

InterruptedExceptionpublicstaticvoidsleep(long

millis,int

nanos)throws

InterruptedException9.3.2線程的優(yōu)先級很多系統(tǒng)在對進程進行調(diào)度時,會采用優(yōu)先級調(diào)度策略。Java中在對線程進行調(diào)度時,也采用了優(yōu)先級調(diào)度策略,具體為:“優(yōu)先級高的線程應(yīng)該有更大的獲取CPU資源而執(zhí)行的概率,優(yōu)先級低的線程并不是總不能執(zhí)行”。也就是說,當(dāng)前正在執(zhí)行的線程優(yōu)先級一般不會比正在準(zhǔn)備狀態(tài)等待執(zhí)行的線程優(yōu)先級低。Java中線程的優(yōu)先級用1~10之間的整數(shù)表示,數(shù)值越大優(yōu)先級越高,默認優(yōu)先級為5。例如,在沒有特別指定的情況下,主線程的優(yōu)先級別為5。另外,對于子線程,其初始優(yōu)先級與其父線程的優(yōu)先級相同。也就是說,若父線程優(yōu)先級為8,則其子線程的初始優(yōu)先級為8。當(dāng)需要改變線程的優(yōu)先級時,可以通過調(diào)用setPriority方法來實現(xiàn),下面為該方法的簽名:publicfinalvoidsetPriority(int

newPriority)9.3.3線程的讓步實際運行中有時需要使當(dāng)前運行的線程讓出CPU,使其他線程得以執(zhí)行,這時就需要使用線程讓步的操作。線程讓步包括兩種方式。線程只是讓出當(dāng)前的CPU資源,具體將CPU讓給誰不確定。線程將給指定的線程讓步,指定的線程沒有完成,其絕不恢復(fù)執(zhí)行。本小節(jié)將對這兩種讓步的方式進行詳細的介紹,具體內(nèi)容如下。1.使用yield方法2.使用join方法9.3.4守護線程前面已經(jīng)提過,其實在Java中根本沒有單線程程序,就算開發(fā)人員只開發(fā)了主線程,后臺還有很多輔助線程,比如線程調(diào)度、內(nèi)存管理等。這些在后臺運行的線程一般稱之為守護線程,本小節(jié)主要介紹如何開發(fā)自己的守護線程。開發(fā)守護線程與普通線程沒有很大的區(qū)別,只要對調(diào)用線程對象的setDaemon方法進行設(shè)置即可,該方法的簽名如下。publicfinalvoidsetDaemon(booleanon)9.4線程的同步多線程程序中,由于同時有多個線程并發(fā)運行,有時會帶來嚴重的問題,甚至引發(fā)錯誤。例如,一個銀行賬戶在同一時刻只能由一個用戶操作,如果兩個用戶同時操作很可能會產(chǎn)生錯誤。為了解決這些問題,在多線程開發(fā)中就需要使用同步技術(shù),本節(jié)將對這方面的知識進行詳細的介紹。9.4.1同步方法簡介同步方法是指用synchronized關(guān)鍵字修飾的方法,其與普通方法的不同是進入同步方法執(zhí)行的線程將獲得同步方法所屬對象的鎖,一旦對象被鎖,其他線程就不能執(zhí)行被鎖對象的任何同步方法。也就是說,線程在執(zhí)行同步方法之前,首先試圖獲得方法所屬對象的鎖,如果不能獲得鎖就進入對象的鎖等待池等待,直到別南叱淌頭潘浠竦盟拍苤蔥小下面給出了聲明同步方法的基本語法。synchronized<返回類型>方法名([參數(shù)列表])[throws<異常序列>]{//同步方法的方法體}9.4.2簡單使用同步方法上一小節(jié)介紹了同步方法與對象鎖的基本知識,本小節(jié)將通過一個完整的例子進行說明。9.4.3線程同步調(diào)度的方法通過前面的介紹可以知道,線程在退出同步方法時將釋放方法所屬對象的鎖。但這并不是全部,在同步方法中還可以使用特定的方法對線程進行調(diào)度,這些方法在處理資源的同步與互斥問題時非常有效。方法簽名功能publicfinalvoidwait()throwsInterruptedException該方法將使得某一線程進入該資源的等待池,使其進入等待狀態(tài),直至別的線程調(diào)用該資源的notify或notifyAll方法將其喚醒為止。該方法將有可能拋出InterruptedException捕獲異常publicfinalvoidwait(longtimeout)throwsInterruptedException參數(shù)timeout為指定的毫秒數(shù),該方法將使得某一線程進入該資源的等待池,使其進入等待狀態(tài),直至到達指定時間或?qū)⑵鋯拘褳橹?。該方法將有可能拋出InterruptedException捕獲異常publicfinalvoidwait(long

timeout,int

nanos)throwsInterruptedException參數(shù)timeout為指定的毫秒數(shù),參數(shù)nanos為指定的額外納秒數(shù),該方法將使得某一線程進入該資源的等待池,使其進入等待狀態(tài),直至到達指定時間或?qū)⑵鋯拘褳橹?。其總時間應(yīng)為timeout毫秒nanos納秒。該方法將有可能拋出InterruptedException捕獲異常publicfinalvoidnotify()該方法將喚醒該資源等待池中的某一個線程。具體會喚醒哪個線程則沒有保障publicfinalvoidnotifyAll()該方法將喚醒該資源等待池中的所有線程9.4.4同步的語句塊前面的幾個小節(jié)介紹了同步的方法,同步的方法在同一時刻只能鎖定一個對象(同步方法所屬的對象),但在并發(fā)執(zhí)行中有時需要鎖定的對象遠不只一個。另外,同步將影響程序的執(zhí)行性能,應(yīng)該盡量減少程序同步的區(qū)域,提高程序的并發(fā)性,而同步方法是無法精確指定同步區(qū)域的。要想解決上述問題,就需要使用同步的語句塊,其基本語法如下。synchronized(<資源對象引用>){//需要進行同步的代碼}9.4.5線程的死鎖任何并發(fā)運行的系統(tǒng)中,當(dāng)有多個訪問者并發(fā)訪問多個互斥的資源時,就有可能造成死鎖的現(xiàn)象。如果系統(tǒng)的設(shè)計不完善,在Java中進行多線程開發(fā)時也有可能造成死鎖。Java中死鎖的含義是:“線程之間互相等待對方釋放資源對象的鎖,而每個線程又持有其他線程需要的鎖,造成幾個線程處在沒有必要的永久等待當(dāng)中,程序無法繼續(xù)運行”。9.4.5線程的死鎖9.5進程同步經(jīng)典示例資源的同步與互斥問題中,最典型的就是“生產(chǎn)者—消費者”問題?!吧a(chǎn)者—消費者”問題的具體含義是,系統(tǒng)中有很多生產(chǎn)者和消費者并發(fā)工作,生產(chǎn)者負責(zé)生產(chǎn)資源,消費者消耗資源。當(dāng)消費者消費資源時,如果資源不足,則需要等待,反之當(dāng)生產(chǎn)者生產(chǎn)資源時,若資源以滿,則也需要等待。另外,同一時刻只能有一個生產(chǎn)者或消費者進行操作。9.5.1“生產(chǎn)者—消費者”案例的框架本書將以在Java中用多線程實現(xiàn)“生產(chǎn)者—消費者”問題模型為例,來討論上一節(jié)所介紹的線程調(diào)度方法的使用。下面首先分別給出了“資源容器”、“生產(chǎn)者”、“消費者”類的代碼。提示:“生產(chǎn)者—消費者”模型也是很好的解決多線程共享一個資源時沖突問題的解決方案,讀者一定要深入理解,在實際開發(fā)中進行應(yīng)用。1.資源類2.生產(chǎn)者類3.消費者9.5.2“生產(chǎn)者—消費者”案例的實際運行上一小節(jié)中給出了“生產(chǎn)者—消費者”案例中需要使用的功能類代碼,本小節(jié)將通過實際運行的情況介紹生產(chǎn)者與消費者線程在運行時是如何協(xié)作的。9.5.3notify方法的使用在上一小節(jié)的“生產(chǎn)者—消費者”案例中,通知等待池中的等待線程使用的是notifyAll方法。本小結(jié)將結(jié)合“生產(chǎn)者—消費者”案例介紹notify方法的使用。9.6volatile關(guān)鍵字的含義與使用前面章節(jié)介紹的基本數(shù)據(jù)

溫馨提示

  • 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

提交評論