




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第一頁在Java程序中使用多線程要比在 C或C+中容易得多,這是因?yàn)镴ava編程語言提供了語言級(jí)的支持。本文通過簡(jiǎn)單的編程示例來說明Java程序中的多線程是多么直觀。讀完本文以后,用戶應(yīng)該能夠編寫簡(jiǎn)單的多線程程序。為什么會(huì)排隊(duì)等待?F面的這個(gè)簡(jiǎn)單的Java程序完成四項(xiàng)不相關(guān)的任務(wù)。這樣的程序有單個(gè)控制線程,控制在這四個(gè)任務(wù)之間線性地移動(dòng)。此外,因?yàn)樗璧?資源?打印機(jī)、磁盤、數(shù)據(jù)庫和顯示屏-由于硬件和軟件的限制都有內(nèi)在的潛伏 時(shí)間,所以每項(xiàng)任務(wù)都包含明顯的等待時(shí)間。因此,程序在訪問數(shù)據(jù)庫之前必須等 待打印機(jī)完成打印文件的任務(wù),等等。如果您正在等待程序的完成,貝U這是對(duì)計(jì)算四項(xiàng)不相關(guān)的任務(wù)資源和
2、您的時(shí)間的一種拙劣使用。改進(jìn)此程序的一種方法是使它成為多線程的。class myclass static p ublic void main( Stri ng argsprin t_a_file(;manipu late_a no ther_file(;access_database(;draw_picture_o n_scree n(;在本例中,每項(xiàng)任務(wù)在開始之前必須等待前一項(xiàng)任務(wù)完成,即使所涉及的任務(wù)毫不相關(guān)也是這樣。但是,在現(xiàn)實(shí)生活中, 我們經(jīng)常使用多線程模型。我們?cè)谔幚砟承┤蝿?wù)的同時(shí)也可以讓孩子、配偶和父母完成別的任務(wù)。例如,我在寫信的同時(shí)可能打發(fā)我的兒子去郵局買郵票。用軟件術(shù)語來說,
3、這稱為多個(gè)控制(或執(zhí)行)線程??梢杂脙煞N不同的方法來獲得多n; P ublic void run( while(true try個(gè)控制線程:多個(gè)進(jìn)程在大多數(shù)操作系統(tǒng)中都可以創(chuàng)建多個(gè)進(jìn)程。當(dāng)一個(gè)程序啟動(dòng)時(shí),它可以為即將開始的每項(xiàng)任務(wù)創(chuàng)建一個(gè)進(jìn)程,并允許它們同時(shí)運(yùn) 行。當(dāng)一個(gè)程序因等待網(wǎng)絡(luò)訪問或用戶輸入而被阻塞時(shí),另一個(gè)程序還可以運(yùn)行, 這樣就增加了資源利用率。但是,按照這種方式創(chuàng)建每個(gè)進(jìn)程要付出一定的代價(jià): 設(shè)置一個(gè)進(jìn)程要占用相當(dāng)一部分處理器時(shí)間和內(nèi)存資源。而且,大多數(shù)操作系統(tǒng)不允許進(jìn)程訪問其他進(jìn)程的內(nèi)存空間。因此,進(jìn)程間的通信很不方便,并且也不會(huì)將它自己提供給容易的編程模型。線程線程也稱為輕型
4、進(jìn)程(LWP。因?yàn)榫€程只能在單個(gè)進(jìn)程的作用域內(nèi)活動(dòng),所以創(chuàng)建線程比創(chuàng)建進(jìn)程要廉價(jià)得多。這 樣,因?yàn)榫€程允許協(xié)作和數(shù)據(jù)交換,并且在計(jì)算資源方面非常廉價(jià),所以線程比進(jìn)Java 編程更可取。線程需要操作系統(tǒng)的支持,因此不是所有的機(jī)器都提供線程。程語言,作為相當(dāng)新的一種語言,已將線程支持與語言本身合為一體,這樣就對(duì)線程提供了強(qiáng)健的支持。使用Java編程語言實(shí)現(xiàn)線程Java編程語言使多線程如此簡(jiǎn)單有效,以致于某些程序員說它實(shí)際上是自然的。 盡管在Java中使用線程比在其他語言中要容易得多,仍然有一些概念需要掌握。要記住的一件重要的事情是 main(函數(shù)也是一個(gè)線程,并可用來做有用的工作。程序員只有在需要
5、多個(gè)線程時(shí)才需要?jiǎng)?chuàng)建新的線程。Thread 類Thread 類是一個(gè)具體的類,即不是抽象類,該類封裝了線程的行為。要?jiǎng)?chuàng)建一個(gè)線程,程序員必須創(chuàng)建一個(gè)從Thread類導(dǎo)出的新類。程序員必須覆蓋 Thread的run(函數(shù)來完成有用的工作。用戶并不直接調(diào)用此函數(shù);而是必須調(diào)用Thread的start(函數(shù),該函數(shù)再調(diào)用run(。下面的代碼說明了它的用法:創(chuàng)建兩個(gè)新線程importjava.util.*;class Time Prin ter exte nds Thread int p auseTime;String n ame;p ublic Time Prin ter(i nt x, Strin
6、g n p auseTime = x;n ame = n;p ublic void run( while(true try System.out. prin tl n(n ame + ":" + newDate(System.curre ntTimeMillis(;Thread.slee p(p auseTime; catch(Exce pti on e System.out. println(e; static p ublic void main( Stri ng argsTime Prin ter tp1 = new Time Prin ter(1000, "
7、Fast Guy"tp 1.start(;Time Printer tp2 = new Time Prin ter(3000, "Slow Guy"tp 2.start(;在本例中,我們可以看到一個(gè)簡(jiǎn)單的程序,它按兩個(gè)不同的時(shí)間間隔( 1秒和3main(共三秒)在屏幕上顯示當(dāng)前時(shí)間。這是通過創(chuàng)建兩個(gè)新線程來完成的,包括個(gè)線程。但是,因?yàn)橛袝r(shí)要作為線程運(yùn)行的類可能已經(jīng)是某個(gè)類層次的一部分,所以就不能再按這種機(jī)制創(chuàng)建線程。雖然在同一個(gè)類中可以實(shí)現(xiàn)任意數(shù)量的接口,但Java編程語言只允許一個(gè)類有一個(gè)父類。同時(shí),某些程序員避免從Thread類導(dǎo)出,因?yàn)樗鼜?qiáng)加了類層次。對(duì)于
8、這種情況,就要runn able 接口。Runn able 接口此接口只有一個(gè)函數(shù),run(,此函數(shù)必須由實(shí)現(xiàn)了此接口的類實(shí)現(xiàn)。但是,就運(yùn)行這個(gè)類而論,其語義與前一個(gè)示例稍有不同。我們可以用runn able接口改寫前一個(gè)示例。(不同的部分用黑體表示。)創(chuàng)建兩個(gè)新線程而不強(qiáng)加類層次import java.util.*;class Time Prin ter imp leme nts Runn able int p auseTime;Stri ng n ame;p ublic Time Prin ter(i nt x, Stri ng n p auseTime = x;n ame =withdr
9、awfloat amt amount -= amt; p ublic floatThread.slee p(pauseTime; catch(Exce pti on e System.out .prin tl n(e; static P ublic void main( Stri ng args Thread t1 = new Thread( newTime Prin ter(1000, "Fast Guy"t1.start(; Thread t2 = new Thread( newTime Prin ter(3000, "Slow Guy" t2.st
10、art(; 請(qǐng)注意,當(dāng)使用runn able接口時(shí),您不能直接創(chuàng)建所需類的對(duì)象并運(yùn)行它;必須從 Thread類的一個(gè)實(shí)例內(nèi)部運(yùn)行它。許多程序員更喜歡runnable接口,因?yàn)閺腡hread類繼承會(huì)強(qiáng)加類層次。sy nchro ni zed關(guān)鍵字至U目前為止,我們看到的示例都只是以非常簡(jiǎn)單的方式來利用線程。只有最小的數(shù)據(jù)流,而且不會(huì)出現(xiàn)兩個(gè)線程訪問同一 個(gè)對(duì)象的情況。但是,在大多數(shù)有用的程序中,線程之間通常有信息流。試考慮一一個(gè)銀行中的多個(gè)金融應(yīng)用程序,它有一個(gè) Accou nt對(duì)象,如下例中所示:項(xiàng)活動(dòng)P ublic class Acco unt String holderName; floa
11、t amount;p ublic Accoun t(Stri ng n ame, float amt holderName = n ame;amount =amt; P ublic void dep ositfloat amt amount += amt; p ublicvoid withdraw(float amt amount -= amt; p ublic floatcheckBala nce( return amou nt; 第二頁在此代碼樣例中潛伏著個(gè)錯(cuò)誤。如果此類用于單線程應(yīng)用程序,不會(huì)有任何問題。但是,在多線程應(yīng)用程序的情況中,不同的線程就有可能同時(shí)訪問同一個(gè)Account對(duì)象,
12、比如說一個(gè)聯(lián)合帳戶的所有者在不同的ATM上同時(shí)進(jìn)行訪問。在這種情況下,存入和支出就可能 以這樣的方式發(fā)生:一個(gè)事務(wù)被另一個(gè)事務(wù)覆蓋。這種情況將是災(zāi)難性的。但是,Java編程語言提供了一種簡(jiǎn)單的機(jī)制來防止發(fā)生這種覆蓋。每個(gè)對(duì)象在運(yùn)行時(shí)都有一個(gè)關(guān)聯(lián)的鎖。這個(gè)鎖可通過為方法添加關(guān)鍵字 syn chro nized來獲得。這樣,修 訂過的Account對(duì)象(如下所示)將不會(huì)遭受像數(shù)據(jù)損壞這樣的錯(cuò)誤:對(duì)一個(gè)銀行中的多項(xiàng)活動(dòng)進(jìn)行同步處理p ublic class Acco unt StringholderName; float amount;p ublic Acco un t(Stri ng n ame,
13、 float amtholderName = n ame;amount = amt; p ublic synchroni zed voidcheckBala nce( retu rn amount; dep osit(和 withdraw(函數(shù)都需要這個(gè)鎖來進(jìn)行操作,所以當(dāng)一個(gè)函數(shù)運(yùn)行時(shí),另一個(gè)函數(shù)就被阻塞。請(qǐng)注意,checkBala nee(未作更改,它嚴(yán)格是一個(gè)讀函數(shù)。因?yàn)閏heckBala nce(未作同步處理,所以任何其他方法都 不會(huì)阻塞它,它也不會(huì)阻塞任何其他方法,不管那些方法是否進(jìn)行了同步處理。Java編程語言中的高級(jí)多線程支持線程組線程是被個(gè)別創(chuàng)建的,但可以機(jī)(JVM調(diào)度算法。將
14、CPU讓給另一個(gè)線程當(dāng)線程放棄某個(gè)稀有的資源將它們歸類到線程組中,以便于調(diào)試和監(jiān)視。只能在創(chuàng)建線程的同時(shí)將它與一個(gè)線程組相關(guān)聯(lián)。在使用大量線程的程序中,使用線程組組織線程可能很有幫助??梢詫⑺鼈兛醋魇怯?jì)算機(jī)上的目錄和文件結(jié)構(gòu)。線程間發(fā)信當(dāng)線程在繼續(xù)執(zhí)行前需要等待一個(gè)條件時(shí),僅有 sy nchronized關(guān)鍵字是不夠的。雖然 synchroni zed關(guān)鍵字阻止并發(fā)更新一個(gè)對(duì)象,但它沒有實(shí)現(xiàn)線程間發(fā)信。Object類為此提供了三個(gè)函數(shù):wait(、notify(和notifyAII(。以全球氣候預(yù)測(cè)程序?yàn)槔?。這些程序通過將地球分為許多單元,在每個(gè)循環(huán)中,每個(gè)單元的計(jì)算都是隔離進(jìn)行的,直到這些值
15、 趨于穩(wěn)定,然后相鄰單元之間就會(huì)交換一些數(shù)據(jù)。所以,從本質(zhì)上講,在每個(gè)循環(huán)中各個(gè)線程都必須等待所有線程完成各自的任務(wù)以后才能進(jìn)入下一個(gè)循環(huán)。這個(gè)模型稱為屏蔽同步,下例說明了這個(gè)模型:屏蔽同步p ublic class BSync int totalThreads;int curre ntThreads;p ublic BSyn c(i nt x totalThreads = x; curre ntThreads = 0;p ublic synchroni zed voidwaitForAII( wait(; catch (Exce pti on e else curre ntThreads =
16、 0;當(dāng)對(duì)一個(gè)線程調(diào)用wait(時(shí),該線程就被有效阻curre ntThreads+;if(curre ntThreads < totalThreads try n otifyAlK;塞,只到另一個(gè)線程對(duì)同一個(gè)對(duì)象調(diào)用 notify(或notifyAll(為止。因此,在前一個(gè) 示例中,不同的線程在完成它們的工作以后將調(diào)用waitForAll(函數(shù),最后一個(gè)線程將觸發(fā)notifyAlK函數(shù),該函數(shù)將釋放所有的線程。第三個(gè)函數(shù)notify(只通知一個(gè)正在等待的線程,當(dāng)對(duì)每次只能由一個(gè)線程使用的資源進(jìn)行訪問限制時(shí),這個(gè)函 數(shù)很有用。但是,不可能預(yù)知哪個(gè)線程會(huì)獲得這個(gè)通知,因?yàn)檫@取決于 Java
17、虛擬(如數(shù)據(jù)庫連接或網(wǎng)絡(luò)端口)時(shí),它可能調(diào)用 yield(函數(shù)臨時(shí)降低自己的優(yōu)先級(jí), 以便某個(gè)其他線程能夠運(yùn)行。守護(hù)線程有兩類線程:用戶線程和守護(hù)線程。用戶線程是那些完成有用工作的線程。守護(hù)線程是那些僅提供輔助功能的線 程。Thread類提供了 setDaemon(函數(shù)。Java程序?qū)⑦\(yùn)行到所有用戶線程終止,然后它將破壞所有的守護(hù)線程。在Java虛擬機(jī)(JVM中,即使在main結(jié)束以后,如果另一個(gè)用戶線程仍在運(yùn)行,則程序仍然可以繼續(xù)運(yùn)行。避免不提倡使用的方法不提倡使用的方法是為支持向后兼容性而保留的那些方法,它們?cè)谝院蟮陌姹局锌赡艹霈F(xiàn),也可能不出現(xiàn)。Java多線程支持在版本1.1和版本1.2中
18、做了重大修訂,stop(、suspend(和resume(函數(shù)已不提倡使用。這些 函數(shù)在JVM中可能引入微妙的錯(cuò)誤。雖然函數(shù)名可能聽起來很誘人,但請(qǐng)抵制誘 惑不要使用它們。調(diào)試線程化的程序在線程化的程序中,可能發(fā)生的某死鎖 死鎖可些常見而討厭的情況是死鎖、活鎖、內(nèi)存損壞和資源耗盡。能是多線程程序最常見的問題。當(dāng)一個(gè)線程需要一個(gè)資源而另一個(gè)線程持有該資源的鎖時(shí),就會(huì)發(fā)生死鎖。這種情況通常很難檢測(cè)。但是,解決方案卻相當(dāng)好:在所 有的線程中按相同的次序獲取所有資源鎖。例如,如果有四個(gè)資源?A、B、C和D?并且一個(gè)線程可能要獲取四個(gè)資源中任何一個(gè)資源的鎖,則請(qǐng)確保在獲取對(duì)B活鎖當(dāng)一個(gè)線程忙于接受新任務(wù)
19、以致它永遠(yuǎn)沒有機(jī)的鎖之前首先獲取對(duì) A的鎖,依此類推。如果 線程T希望獲取對(duì)B和C的鎖, 而 線程2”獲取了 A、C和D的鎖,則這一技術(shù)可能導(dǎo)致阻塞,但它永遠(yuǎn)不會(huì)在這 四個(gè)鎖上造成死鎖。會(huì)完成任何任務(wù)時(shí),就會(huì)發(fā)生活鎖。這個(gè)線程最終將超出緩沖區(qū)并導(dǎo)致程序崩潰。 試想一個(gè)秘書需要錄入一封信,但她一直在忙于接電話,所以這封信永遠(yuǎn)不會(huì)被錄 入。 內(nèi)存損壞 如果明智地使用synchronized關(guān)鍵字,則完全可以避免內(nèi) 存錯(cuò)誤這種氣死人的問題。資源耗盡某些系統(tǒng)資源是有限的,如文件描述符。多線程程序可能耗盡資源,因?yàn)槊總€(gè)線程都可能希望有一個(gè)這樣的資源。如 果線程數(shù)相當(dāng)大,或者某個(gè)資源的侯選線程數(shù)遠(yuǎn)遠(yuǎn)超過了
20、可用的資源數(shù),則最好使 用資源池。一個(gè)最好的示例是數(shù)據(jù)庫連接池。只要線程需要使用一個(gè)數(shù)據(jù)庫連 接,它就從池中取出一個(gè),使用以后再將它返回池中。資源池也稱為 資源庫。 調(diào)試大量的線程 有時(shí)一個(gè)程序因?yàn)橛写罅康木€程在運(yùn)行而極難調(diào)試。在這種情況下,下面的這個(gè)類可能會(huì)派上用場(chǎng):P ublic class P robe exte nds ThreadThread x = newThread t = xi;Java線程模1到10之間的一 p ublic P robe( p ublic void run( while(true Thread100;Thread.e numerate(x;for(i nt i=0; i<100; i+ if(t = n ull break; elseSystem.out .println(t.getName( + "t" + t.get Priority(+ "t" + t.isAlive( + "t" +t.isDaemo n(;限制線程優(yōu)先級(jí)和調(diào)度型涉及可以動(dòng)態(tài)更改的線程優(yōu)先級(jí)。本質(zhì)上,線程的優(yōu)先級(jí)是從 個(gè)數(shù)字,數(shù)字越大表明任務(wù)越緊急。JVM標(biāo)準(zhǔn)首先
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二年級(jí)下冊(cè)數(shù)學(xué)教案- 撥一撥 北師大版
- 2025年中學(xué)職務(wù)崗位聘用合同
- 五年級(jí)下冊(cè)數(shù)學(xué)教案-6.5 圖形與幾何(平面圖形的周長(zhǎng)和面積(復(fù)習(xí))) ▏滬教版
- 人教版數(shù)學(xué)三年級(jí)上冊(cè)單元練習(xí)卷(易錯(cuò)題)-第五單元-倍的認(rèn)識(shí)(含答案)
- 2024年快速熱處理設(shè)備項(xiàng)目資金籌措計(jì)劃書代可行性研究報(bào)告
- 2024年灌裝包裝設(shè)備項(xiàng)目投資申請(qǐng)報(bào)告代可行性研究報(bào)告
- 2025年廣西金融職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫審定版
- 2025年貴州建設(shè)職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)傾向性測(cè)試題庫帶答案
- 2025屆黑龍江省“六校聯(lián)盟”高三上學(xué)期聯(lián)考生物試題及答案
- 別墅家裝保障合同范本
- 《物權(quán)法》本科題集
- 新能源汽車驅(qū)動(dòng)電機(jī)及控制系統(tǒng)檢修課件 學(xué)習(xí)情境6:電機(jī)控制系統(tǒng)檢修
- 廚房菜品出品標(biāo)準(zhǔn)培訓(xùn)
- 2024年福建省公務(wù)員錄用考試《行測(cè)》試題及答案解析
- 【基于單片機(jī)的超市自動(dòng)存儲(chǔ)柜的設(shè)計(jì)與實(shí)現(xiàn)(論文)8700字】
- 保證金退還協(xié)議書
- 2024年銀行考試-商業(yè)銀行考試近5年真題附答案
- 招聘筆試題與參考答案(某大型央企)2024年
- 全國(guó)裝配式建筑職業(yè)技能競(jìng)賽考試題庫
- Nikon尼康D3100中文說明書
- 2023年廣西職業(yè)院校技能大賽高職組《Python程序開發(fā)》賽項(xiàng)競(jìng)賽樣題
評(píng)論
0/150
提交評(píng)論