九九热最新网址,777奇米四色米奇影院在线播放,国产精品18久久久久久久久久,中文有码视频,亚洲一区在线免费观看,国产91精品在线,婷婷丁香六月天

歡迎來(lái)到裝配圖網(wǎng)! | 幫助中心 裝配圖網(wǎng)zhuangpeitu.com!
裝配圖網(wǎng)
ImageVerifierCode 換一換
首頁(yè) 裝配圖網(wǎng) > 資源分類(lèi) > PPT文檔下載  

Java語(yǔ)言程序設(shè)計(jì)第08章.ppt

  • 資源ID:11496801       資源大?。?span id="24d9guoke414" class="font-tahoma">350.50KB        全文頁(yè)數(shù):24頁(yè)
  • 資源格式: PPT        下載積分:9.9積分
快捷下載 游客一鍵下載
會(huì)員登錄下載
微信登錄下載
三方登錄下載: 微信開(kāi)放平臺(tái)登錄 支付寶登錄   QQ登錄   微博登錄  
二維碼
微信掃一掃登錄
下載資源需要9.9積分
郵箱/手機(jī):
溫馨提示:
用戶名和密碼都是您填寫(xiě)的郵箱或者手機(jī)號(hào),方便查詢(xún)和重復(fù)下載(系統(tǒng)自動(dòng)生成)
支付方式: 支付寶    微信支付   
驗(yàn)證碼:   換一換

 
賬號(hào):
密碼:
驗(yàn)證碼:   換一換
  忘記密碼?
    
友情提示
2、PDF文件下載后,可能會(huì)被瀏覽器默認(rèn)打開(kāi),此種情況可以點(diǎn)擊瀏覽器菜單,保存網(wǎng)頁(yè)到桌面,就可以正常下載了。
3、本站不支持迅雷下載,請(qǐng)使用電腦自帶的IE瀏覽器,或者360瀏覽器、谷歌瀏覽器下載即可。
4、本站資源下載后的文檔和圖紙-無(wú)水印,預(yù)覽文檔經(jīng)過(guò)壓縮,下載后原文更清晰。
5、試題試卷類(lèi)文檔,如果標(biāo)題沒(méi)有明確說(shuō)明有答案則都視為沒(méi)有答案,請(qǐng)知曉。

Java語(yǔ)言程序設(shè)計(jì)第08章.ppt

第8章多線程編程,支持多線程編程是Java語(yǔ)言的又一大特色。多線程是相對(duì)于進(jìn)程或單線程而言的,它具有并發(fā)性、執(zhí)行效率高的特點(diǎn)。本章將對(duì)Java中的多線程編程作初步介紹。,8.1多線程編程概述8.2線程的創(chuàng)建8.3線程的優(yōu)先級(jí)8.4線程同步8.5線程間通信8.6線程的控制,Return,8.1多線程編程概述,本節(jié)介紹多線程編程的基礎(chǔ)知識(shí),包括多線程的基本概念、Java的線程模型(線程優(yōu)先級(jí)、同步性、消息傳遞)等方面的內(nèi)容。,8.1.1什么是多線程8.1.2Java線程模型,Return,8.1.1什么是多線程,同其他大多數(shù)編程語(yǔ)言不同,Java內(nèi)置支持多線程編程(multithreadedprogramming)。多線程程序包含兩條或兩條以上并發(fā)運(yùn)行的部分,把程序中每個(gè)這樣的部分都叫作一個(gè)線程(thread)。每個(gè)線程都有獨(dú)立的執(zhí)行路徑,因此多線程是多任務(wù)處理的一種特殊形式。讀者可能知道多任務(wù)處理,它實(shí)際上被所有的現(xiàn)代操作系統(tǒng)所支持。然而,多任務(wù)處理有兩種截然不同的類(lèi)型:基于進(jìn)程的和基于線程的。搞清楚兩者的區(qū)別是很重要的。對(duì)大多數(shù)讀者來(lái)說(shuō),基于進(jìn)程的多任務(wù)處理是更熟悉的形式。進(jìn)程(process)本質(zhì)上是一個(gè)執(zhí)行的程序。因此基于進(jìn)程的多任務(wù)處理的特點(diǎn)是允許你的計(jì)算機(jī)同時(shí)運(yùn)行兩個(gè)或更多的程序。舉例來(lái)說(shuō),基于進(jìn)程的多任務(wù)處理使你在運(yùn)用文本編輯器的時(shí)候可以同時(shí)運(yùn)行Java編譯器。在基于進(jìn)程的多任務(wù)處理中,程序是調(diào)度程序所分派的最小代碼單位。而在基于線程(thread-based)的多任務(wù)處理環(huán)境中,線程是最小的執(zhí)行單位。這意味著一個(gè)程序可以同時(shí)執(zhí)行兩個(gè)或者多個(gè)任務(wù)的功能。例如,一個(gè)文本編輯器可以在打印的同時(shí)格式化文本。所以,多進(jìn)程程序處理“大圖片”,而多線程程序處理細(xì)節(jié)問(wèn)題。,Return,多線程程序比多進(jìn)程程序需要更少的管理費(fèi)用。進(jìn)程是重量級(jí)的任務(wù),需要分配給它們獨(dú)立的地址空間。進(jìn)程間通信是昂貴和受限的。進(jìn)程間的轉(zhuǎn)換也是很需要花費(fèi)的。另一方面,線程是輕量級(jí)的選手。它們共享相同的地址空間并且共同分享同一個(gè)進(jìn)程。線程間通信是便宜的,線程間的轉(zhuǎn)換也是低成本的。當(dāng)Java程序使用多進(jìn)程任務(wù)處理環(huán)境時(shí),多進(jìn)程程序不受Java的控制,而多線程則受Java控制。多線程可幫助你編寫(xiě)出CPU最大利用率的高效程序,使得空閑時(shí)間保持最低。這對(duì)Java運(yùn)行的交互式的網(wǎng)絡(luò)互連環(huán)境是至關(guān)重要的,因?yàn)榭臻e時(shí)間是公共的。例如,網(wǎng)絡(luò)的數(shù)據(jù)傳輸速率遠(yuǎn)低于計(jì)算機(jī)處理能力,而本地文件系統(tǒng)資源的讀寫(xiě)速度也遠(yuǎn)低于CPU的處理能力。當(dāng)然,用戶輸入也比計(jì)算機(jī)慢很多。在傳統(tǒng)的單線程環(huán)境中,程序必須等待每一個(gè)這樣的任務(wù)完成以后才能執(zhí)行下一步盡管CPU有很多空閑時(shí)間。多線程使你能夠獲得并充分利用這些空閑時(shí)間。,8.1.2Java線程模型,Java運(yùn)行系統(tǒng)在很多方面依賴(lài)于線程,所有的類(lèi)庫(kù)設(shè)計(jì)都考慮到多線程。實(shí)際上,Java使用線程來(lái)使整個(gè)環(huán)境異步。這有利于通過(guò)防止CPU循環(huán)的浪費(fèi)來(lái)減少無(wú)效部分。為更好地理解多線程環(huán)境的優(yōu)勢(shì),我們可以將它與它的對(duì)照物相比較。單線程系統(tǒng)的處理途徑是使用一種叫作輪詢(xún)的事件循環(huán)方法。在該模型中,單線程控制在一無(wú)限循環(huán)中運(yùn)行,輪詢(xún)一個(gè)事件序列來(lái)決定下一步做什么。一旦輪詢(xún)裝置返回信號(hào)表明已準(zhǔn)備好讀取網(wǎng)絡(luò)文件,事件循環(huán)調(diào)度控制管理到適當(dāng)?shù)氖录幚沓绦?。直到事件處理程序返回,系統(tǒng)中沒(méi)有其他事件發(fā)生。這就浪費(fèi)了CPU時(shí)間。這導(dǎo)致了程序的一部分獨(dú)占了系統(tǒng),阻止了其他事件的執(zhí)行。總的來(lái)說(shuō),單線程環(huán)境,當(dāng)一個(gè)線程因?yàn)榈却Y源時(shí)阻塞(block,掛起執(zhí)行),整個(gè)程序停止運(yùn)行。,Java多線程的優(yōu)點(diǎn)就在于取消了主循環(huán)/輪詢(xún)機(jī)制。一個(gè)線程可以暫停而不影響程序的其他部分。例如,當(dāng)一個(gè)線程從網(wǎng)絡(luò)讀取數(shù)據(jù)或等待用戶輸入時(shí)產(chǎn)生的空閑時(shí)間可以被利用到其他地方。多線程允許活的循環(huán)在每一幀間隙中沉睡一秒而不暫停整個(gè)系統(tǒng)。在Java程序中出現(xiàn)線程阻塞,僅有一個(gè)線程暫停,其他線程繼續(xù)運(yùn)行。線程存在多種狀態(tài)。線程可以正在運(yùn)行(running),只要獲得了CPU時(shí)間它就可以運(yùn)行;運(yùn)行的線程可以被掛起(suspend),并臨時(shí)中斷它的執(zhí)行;一個(gè)掛起的線程可以被恢復(fù)(resume),允許它從停止的地方繼續(xù)運(yùn)行;一個(gè)線程可以在等待資源時(shí)被阻塞(block);在任何時(shí)候,線程可以被終止(terminate),這將立即中斷運(yùn)行。一旦終止,線程不能被恢復(fù)。線程的各狀態(tài)間關(guān)系見(jiàn)教材P190頁(yè)圖8-1所示。,下面簡(jiǎn)要介紹與Java線程相關(guān)的幾個(gè)概念,Java給每個(gè)線程安排優(yōu)先級(jí)以決定與其他線程比較時(shí)該如何對(duì)待該線程。線程優(yōu)先級(jí)是詳細(xì)說(shuō)明線程間優(yōu)先關(guān)系的整數(shù)。作為絕對(duì)值,優(yōu)先級(jí)是毫無(wú)意義的;當(dāng)只有一個(gè)線程時(shí),優(yōu)先級(jí)高的線程并不比優(yōu)先級(jí)低的線程運(yùn)行的快。相反,線程的優(yōu)先級(jí)是用來(lái)決定何時(shí)從一個(gè)運(yùn)行的線程切換到另一個(gè)。這叫“上下文轉(zhuǎn)換”(contextswitch)。決定上下文轉(zhuǎn)換發(fā)生的規(guī)則很簡(jiǎn)單:l線程可以自動(dòng)放棄控制。在I/O未決定的情況下,睡眠或阻塞由明確的讓步來(lái)完成。在這種假定下,所有其他的線程被檢測(cè),準(zhǔn)備運(yùn)行的最高優(yōu)先級(jí)線程被授予CPU。l線程可以被高優(yōu)先級(jí)的線程搶占。在這種情況下,低優(yōu)先級(jí)線程不主動(dòng)放棄,處理器只是被先占無(wú)論它正在干什么處理器被高優(yōu)先級(jí)的線程占據(jù)?;旧希坏└邇?yōu)先級(jí)線程要運(yùn)行,它就執(zhí)行。這叫做有優(yōu)先級(jí)的多任務(wù)處理。當(dāng)兩個(gè)相同優(yōu)先級(jí)的線程競(jìng)爭(zhēng)CPU周期時(shí),情形有一點(diǎn)復(fù)雜。對(duì)于Windows這樣的操作系統(tǒng),等優(yōu)先級(jí)的線程是在循環(huán)模式下自動(dòng)劃分時(shí)間的。對(duì)于其他一些非Windows操作系統(tǒng)而,如Solaris2.x,等優(yōu)先級(jí)線程相對(duì)于它們的對(duì)等體自動(dòng)放棄。如果不這樣,其他的線程就不會(huì)運(yùn)行。,1線程優(yōu)先級(jí),2同步性,由于多線程在程序中引入了一個(gè)異步行為,故在需要的時(shí)候必須有加強(qiáng)同步性的方法。舉例來(lái)說(shuō),如果你希望兩個(gè)線程相互通信并共享一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),例如鏈表序列,就需要某些方法來(lái)確保它們沒(méi)有相互沖突。也就是說(shuō),你必須防止一個(gè)線程寫(xiě)入數(shù)據(jù)而另一個(gè)線程正在讀取鏈表中的數(shù)據(jù)。為此,Java在進(jìn)程間同步性的老模式基礎(chǔ)上實(shí)行了另外的一種方法:管程(monitor)。管程是一種由C.A.R.Hoare首先定義的控制機(jī)制。你可以把管程想象成一個(gè)僅控制一個(gè)線程的小盒子。一旦線程進(jìn)入管程,所有線程必須等待直到該線程退出了管程。用這種方法,管程可以用來(lái)防止共享的資源被多個(gè)線程操縱。很多多線程系統(tǒng)將管程作為程序必須明確的引用和操作的對(duì)象。但Java提供一個(gè)清晰的解決方案,不提供“Monitor”類(lèi);相反,每個(gè)對(duì)象都擁有自己的隱式管程,當(dāng)對(duì)象的同步方法被調(diào)用時(shí)管程自動(dòng)載入。一旦一個(gè)線程包含在一個(gè)同步方法中,沒(méi)有其他線程可以調(diào)用相同對(duì)象的同步方法。這就使你可以編寫(xiě)非常清晰和簡(jiǎn)潔的多線程代碼,因?yàn)橥街С质钦Z(yǔ)言?xún)?nèi)置的。,3消息傳遞,當(dāng)把程序分成若干線程后,就要定義各線程之間的聯(lián)系。用大多數(shù)其他語(yǔ)言規(guī)劃時(shí)必須依賴(lài)于操作系統(tǒng)來(lái)確立線程間通信,這樣當(dāng)然要增加花費(fèi)。然而,Java提供了多線程間談話清潔的、低成本的途徑通過(guò)調(diào)用所有對(duì)象都有的預(yù)先確定的方法。Java的消息傳遞系統(tǒng)允許一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)同步方法,然后在那里等待,一直等到其他線程明確通知它出來(lái)。,Return,Java的多線程系統(tǒng)建立于Thread類(lèi)、方法以及共伴接口Runnable基礎(chǔ)上。Thread類(lèi)封裝了線程的執(zhí)行。既然不能直接引用運(yùn)行著的線程的狀態(tài),就要通過(guò)它的代理處理它。于是Thread實(shí)例產(chǎn)生了。為創(chuàng)建一個(gè)新的線程,程序中必須擴(kuò)展Thread或?qū)崿F(xiàn)Runnable接口。Thread類(lèi)定義了好幾種方法來(lái)幫助管理線程,見(jiàn)教材P192頁(yè)表8-1中所列。,4Thread類(lèi)和Runnable接口,8.2線程的創(chuàng)建,本節(jié)介紹在Java中如何創(chuàng)建線程。主要內(nèi)容包括主線程、多線程的創(chuàng)建、相關(guān)方法的使用等。,8.2.1關(guān)于主線程8.2.2創(chuàng)建一個(gè)線程8.2.3創(chuàng)建多線程8.2.4使用isAlive()和join(),Return,8.2.1關(guān)于主線程,當(dāng)Java程序啟動(dòng)時(shí),一個(gè)線程立刻運(yùn)行,該線程通常就叫做程序的主線程(mainthread),因?yàn)樗浅绦蜷_(kāi)始時(shí)就執(zhí)行的。主線程的重要性主要體現(xiàn)在兩方面:l它是產(chǎn)生其他子線程的線程;l通常它必須最后完成執(zhí)行,因?yàn)樗鼒?zhí)行各種關(guān)閉動(dòng)作。盡管主線程在程序啟動(dòng)時(shí)自動(dòng)創(chuàng)建,但它可以由一個(gè)Thread對(duì)象控制。為此,必須調(diào)用方法currentThread()獲得它的一個(gè)引用,currentThread()是Thread類(lèi)的公有的靜態(tài)成員。它的一般形式如下staticThreadcurrentThread()該方法返回一個(gè)調(diào)用它的線程的引用。一旦獲得主線程的引用,就可以像控制其他線程那樣控制主線程。下面我們考察一下教材P192193頁(yè)的程序代碼。在上面的程序中,當(dāng)前線程(當(dāng)然是主線程)的引用通過(guò)調(diào)用currentThread()獲得,該引用保存在局部變量t中。然后,程序顯示了線程的信息。接著,程序調(diào)用setName()改變線程的內(nèi)部名稱(chēng),線程信息又被顯示。然后,一個(gè)循環(huán)數(shù)從5開(kāi)始遞減,每數(shù)一次暫停一秒。暫停是由sleep()方法來(lái)完成的,sleep()語(yǔ)句明確規(guī)定延遲時(shí)間是1毫秒。請(qǐng)讀者注意循環(huán)外的try/catch塊。Thread類(lèi)的sleep()方法可能引發(fā)一個(gè)InterruptedException異常,這種情形會(huì)在其他線程想要打攪沉睡線程時(shí)發(fā)生。本例只是打印了它是否被打斷的消息。在實(shí)際的程序中,必須靈活處理此類(lèi)問(wèn)題。,Return,8.2.2創(chuàng)建一個(gè)線程,大多數(shù)情況,通過(guò)實(shí)例化一個(gè)Thread對(duì)象來(lái)創(chuàng)建一個(gè)線程。Java定義了兩種方式:l實(shí)現(xiàn)Runnable接口;l以繼承Thread類(lèi)的方式。,創(chuàng)建線程最簡(jiǎn)單的方法就是創(chuàng)建一個(gè)實(shí)現(xiàn)Runnable接口的類(lèi),Runnable抽象了一個(gè)執(zhí)行代碼單元。可以通過(guò)實(shí)現(xiàn)Runnable接口的方法創(chuàng)建每一個(gè)對(duì)象的線程。為實(shí)現(xiàn)Runnable接口,一個(gè)類(lèi)僅需實(shí)現(xiàn)一個(gè)run()的簡(jiǎn)單方法,該方法聲明如下:publicvoidrun()在run()中,可以定義代碼來(lái)構(gòu)建新的線程。重要的是:run()方法能夠像主線程那樣調(diào)用其他方法,引用其他類(lèi),聲明變量。僅有的不同是:run()在程序中確立另一個(gè)并發(fā)的線程執(zhí)行入口。當(dāng)run()返回時(shí),該線程結(jié)束。在已經(jīng)創(chuàng)建了實(shí)現(xiàn)Runnable接口的類(lèi)以后,需要在類(lèi)內(nèi)部實(shí)例化一個(gè)Thread類(lèi)的對(duì)象。Thread類(lèi)定義了好幾種構(gòu)造函數(shù)。我們會(huì)用到的如下:Thread(RunnablethreadOb,StringthreadName)在該構(gòu)造函數(shù)中,threadOb是一個(gè)實(shí)現(xiàn)Runnable接口類(lèi)的實(shí)例。這定義了線程執(zhí)行的起點(diǎn),新線程的名稱(chēng)由threadName定義。建立新的線程后,它并不運(yùn)行直到調(diào)用其start()方法,該方法在Thread類(lèi)中定義。從本質(zhì)上講,start()執(zhí)行的是一個(gè)對(duì)run()的調(diào)用。start()方法聲明如下:voidstart(),下面我們分別對(duì)這兩種方法進(jìn)行介紹:,1實(shí)現(xiàn)Runnable接口,2擴(kuò)展Thread,創(chuàng)建線程的另一個(gè)途徑是創(chuàng)建一個(gè)新類(lèi)來(lái)擴(kuò)展Thread類(lèi),然后再創(chuàng)建該類(lèi)的實(shí)例。當(dāng)一個(gè)類(lèi)繼承Thread時(shí),它必須重載run()方法,這個(gè)run()方法是新線程的入口。同時(shí),它也必須調(diào)用start()方法去啟動(dòng)新線程執(zhí)行。,Return,到這里,讀者可能會(huì)奇怪為什么Java有兩種創(chuàng)建子線程的方法,哪一種更好呢。所有的問(wèn)題都?xì)w于一點(diǎn)。Thread類(lèi)定義了多種方法可以被派生類(lèi)重載。對(duì)于所有的方法,唯一的必須被重載的是run()方法。這當(dāng)然是實(shí)現(xiàn)Runnable接口所需的同樣的方法。很多Java程序員認(rèn)為類(lèi)僅在它們被加強(qiáng)或修改時(shí)被擴(kuò)展。因此,如果你不重載Thread的其他方法,最好只實(shí)現(xiàn)Runnable接口,這當(dāng)然由自己決定。在本章的其他部分,我們應(yīng)用實(shí)現(xiàn)Runnable接口的類(lèi)來(lái)創(chuàng)建線程。,3選擇合適的方法,8.2.3創(chuàng)建多線程,到目前為止,我們僅用到兩個(gè)線程:主線程和一個(gè)子線程。然而,我們完全可以創(chuàng)建所需的更多線程。例如,教材P197198頁(yè)的程序創(chuàng)建了3個(gè)子線程。詳細(xì)分析該程序。,Return,8.2.4使用isAlive()和join(),如前所述,我們一般是希望主線程最后結(jié)束。在上面的例子中,這點(diǎn)是通過(guò)在main()中調(diào)用sleep()來(lái)實(shí)現(xiàn)的,經(jīng)過(guò)足夠長(zhǎng)時(shí)間的延遲以確保所有子線程都先于主線程結(jié)束。然而,這并不是一個(gè)好的解決方法。因?yàn)橛袝r(shí)候存在這個(gè)問(wèn)題:一個(gè)線程如何知道另一線程已經(jīng)結(jié)束?幸運(yùn)的是,Thread類(lèi)提供了解決此問(wèn)題的有效方法。有兩種方法可以判定一個(gè)線程是否結(jié)束:第一,可以在線程中調(diào)用isAlive()。這種方法由Thread定義,它的一般形式如下finalbooleanisAlive()如果所調(diào)用線程仍在運(yùn)行,isAlive()方法返回true,如果不是則返回false。但isAlive()很少用到,等待線程結(jié)束的更常用的方法是調(diào)用join(),描述如下finalvoidjoin()throwsInterruptedException該方法等待所調(diào)用線程結(jié)束,該名字來(lái)自于要求線程等待直到指定線程參與的概念。join()的附加形式允許給等待指定線程結(jié)束定義一個(gè)最大時(shí)間。詳細(xì)分析教材P199200頁(yè)的程序。,Return,8.3線程的優(yōu)先級(jí),線程優(yōu)先級(jí)被線程調(diào)度用來(lái)判定何時(shí)某個(gè)線程允許運(yùn)行。理論上,優(yōu)先級(jí)高的線程比優(yōu)先級(jí)低的線程獲得更多的CPU時(shí)間。實(shí)際上,線程獲得的CPU時(shí)間通常由包括優(yōu)先級(jí)在內(nèi)的多個(gè)因素決定。一個(gè)優(yōu)先級(jí)高的線程自然比優(yōu)先級(jí)低的線程優(yōu)先。理論上,等優(yōu)先級(jí)線程有同等的權(quán)利使用CPU,但你必須小心。需要記住的是,Java是被設(shè)計(jì)成能在很多環(huán)境下工作的。不同環(huán)境下實(shí)現(xiàn)多任務(wù)處理從本質(zhì)上來(lái)看是可能的。為安全起見(jiàn),等優(yōu)先級(jí)線程有時(shí)候也受到控制。這保證了所有線程在無(wú)優(yōu)先級(jí)的操作系統(tǒng)下都有機(jī)會(huì)運(yùn)行。實(shí)際上,在無(wú)優(yōu)先級(jí)的環(huán)境下,多數(shù)線程仍然有機(jī)會(huì)運(yùn)行,因?yàn)楹芏嗑€程不可避免地會(huì)遭遇阻塞,例如等待輸入輸出。遇到這種情形,阻塞的線程掛起,其他線程運(yùn)行。但是如果你希望多線程執(zhí)行得順利的話,最好不要采用這種方法。同樣,有些類(lèi)型的任務(wù)是占CPU的。對(duì)于這些支配CPU類(lèi)型的線程,有時(shí)你希望能夠支配它們,以便使其他線程可以運(yùn)行。設(shè)置線程的優(yōu)先級(jí),用setPriority()方法,該方法也是Thread的成員。它的通常形式為finalvoidsetPriority(intlevel)這里,level指定了對(duì)所調(diào)用的線程的新的優(yōu)先權(quán)的設(shè)置。Level的值必須在MIN_PRIORITY到MAX_PRIORITY范圍內(nèi)。通常,它們的值分別是1和10。要返回一個(gè)線程為默認(rèn)的優(yōu)先級(jí),指定NORM_PRIORITY,通常值為5。這些優(yōu)先級(jí)在Thread中都被定義為final型變量。,Return,8.4線程同步,當(dāng)兩個(gè)或兩個(gè)以上的線程需要共享資源,它們需要某種方法來(lái)確定資源在某一刻僅被一個(gè)線程占用,達(dá)到此目的的過(guò)程叫做同步(synchronization)。Java為此提供了獨(dú)特的、很有效的支持機(jī)制。,8.4.1使用同步方法8.4.2同步語(yǔ)句,Return,8.4.1使用同步方法,同步的關(guān)鍵是管程(也叫信號(hào)量,即semaphore)的概念。管程是一個(gè)互斥獨(dú)占鎖定的對(duì)象,或稱(chēng)互斥體(mutex)。在給定的時(shí)間,僅有一個(gè)線程可以獲得管程。當(dāng)一個(gè)線程需要鎖定時(shí),它必須進(jìn)入管程。所有其他的試圖進(jìn)入已經(jīng)鎖定的管程的線程必須掛起直到第一個(gè)線程退出管程。這些其他的線程被稱(chēng)為等待管程。我們可以用兩種方法同步化代碼。通過(guò)調(diào)用sleep(),call()方法允許執(zhí)行轉(zhuǎn)換到另一個(gè)線程。兩者都包括synchronized關(guān)鍵字的運(yùn)用。分析教材P204頁(yè)的示例。,Return,8.4.2同步語(yǔ)句,盡管在創(chuàng)建的類(lèi)的內(nèi)部創(chuàng)建同步方法是獲得同步的簡(jiǎn)單和有效的方法,但它并非在任何時(shí)候都有效。假設(shè)你想獲得不為多線程訪問(wèn)設(shè)計(jì)的類(lèi)對(duì)象的同步訪問(wèn),也就是該類(lèi)沒(méi)有用到synchronized方法。而且,該類(lèi)不是你自己,而是第三方創(chuàng)建的,就不能獲得它的源代碼。這樣,就不能在相關(guān)方法前加synchronized修飾符。怎樣才能使該類(lèi)的一個(gè)對(duì)象同步化呢?解決的方法很簡(jiǎn)單:只需將對(duì)這個(gè)類(lèi)定義的方法的調(diào)用放入一個(gè)synchronized塊內(nèi)就可以了。下面是synchronized語(yǔ)句的一般形式synchronized(object)/statementstobesynchronized其中,object是對(duì)同步對(duì)象的引用。如果你想要同步的只是一個(gè)語(yǔ)句,那么不需要花括號(hào)。一個(gè)同步塊確保對(duì)object成員方法的調(diào)用僅在當(dāng)前線程成功進(jìn)入object管程后發(fā)生。,Return,8.5線程間通信,前面的例子無(wú)條件地阻塞了其他線程異步訪問(wèn)某個(gè)方法。Java對(duì)象中隱式管程的應(yīng)用是很強(qiáng)大的,但是我們可以通過(guò)進(jìn)程間通信達(dá)到更微妙的境界,這在Java中是很簡(jiǎn)單的。,8.5.1Java中的線程通訊8.5.2關(guān)于死鎖,Return,8.5.1Java中的線程通訊,多線程通過(guò)把任務(wù)分成離散的和合乎邏輯的單元代替了事件循環(huán)程序。線程還有另外一個(gè)優(yōu)點(diǎn):它遠(yuǎn)離了輪詢(xún)。輪詢(xún)通常由重復(fù)監(jiān)測(cè)條件的循環(huán)實(shí)現(xiàn)。一旦條件成立,就要采取適當(dāng)?shù)男袆?dòng)。這浪費(fèi)了CPU時(shí)間。為避免輪詢(xún),Java包含了通過(guò)wait(),notify()和notifyAll()方法實(shí)現(xiàn)的一個(gè)進(jìn)程間通信機(jī)制。這些方法在對(duì)象中是用final方法實(shí)現(xiàn)的,所以所有的類(lèi)都含有它們。這三個(gè)方法僅在synchronized方法中才能被調(diào)用。盡管這些方法從計(jì)算機(jī)科學(xué)遠(yuǎn)景方向上來(lái)說(shuō)具有概念的高度先進(jìn)性,實(shí)際中用起來(lái)卻是很簡(jiǎn)單的。wait()告知被調(diào)用的線程放棄管程進(jìn)入睡眠直到其他線程進(jìn)入相同管程并且調(diào)用notify()。notify()恢復(fù)相同對(duì)象中第一個(gè)調(diào)用wait()的線程。notifyAll()恢復(fù)相同對(duì)象中所有調(diào)用wait()的線程。這些方法在Object中被聲明,如下所示finalvoidwait()throwsInterruptedExceptionfinalvoidnotify()finalvoidnotifyAll()wait()存在的另外的形式允許你定義等待時(shí)間。分析教材P207210頁(yè)的程序段。,Return,8.5.2關(guān)于死鎖,需要避免的與多任務(wù)處理有關(guān)的特殊錯(cuò)誤類(lèi)型是死鎖(deadlock)。死鎖發(fā)生在當(dāng)兩個(gè)線程對(duì)一對(duì)同步對(duì)象有循環(huán)依賴(lài)關(guān)系時(shí)。例如,假定一個(gè)線程進(jìn)入了對(duì)象X的管程而另一個(gè)線程進(jìn)入了對(duì)象Y的管程。如果X的線程試圖調(diào)用Y的同步方法,它將像預(yù)料的一樣被鎖定。而Y的線程同樣希望調(diào)用X的一些同步方法,線程永遠(yuǎn)等待,因?yàn)闉榈竭_(dá)X,必須釋放自己的Y的鎖定以使第一個(gè)線程可以完成。死鎖是很難調(diào)試的錯(cuò)誤,這是因?yàn)椋旱谝?,通常它極少發(fā)生,只有到兩線程的時(shí)間段剛好符合時(shí)才能發(fā)生;第二,它可能包含多于兩個(gè)的線程和同步對(duì)象。也就是說(shuō),死鎖在比剛講述的例子有更多復(fù)雜的事件序列的時(shí)候可以發(fā)生。為充分理解死鎖,觀察它的行為是很有用的。教材P211212頁(yè)的例子生成了兩個(gè)類(lèi),A和B,分別有foo()和bar()方法。這兩種方法在調(diào)用其他類(lèi)的方法前有一個(gè)短暫的停頓。主類(lèi),名為Deadlock,創(chuàng)建了A和B的實(shí)例,然后啟動(dòng)第二個(gè)線程去設(shè)置死鎖環(huán)境。foo()和bar()方法使用sleep()強(qiáng)迫死鎖現(xiàn)象發(fā)生。程序死鎖,需要按CTRL-C來(lái)結(jié)束程序。在PC機(jī)上按CTRL-BREAK(或在Solaris下按CTRL-)可以看到全線程和管程緩沖堆。,Return,8.6線程的控制,本節(jié)討論有關(guān)線程控制的問(wèn)題,包括線程的掛起、恢復(fù)、終止等方面的問(wèn)題。,8.6.1掛起、恢復(fù)和終止線程8.6.2Java2中的線程控制8.6.3使用instanceof,Return,8.6.1掛起、恢復(fù)和終止線程,有時(shí),線程的掛起是很有用的。例如,一個(gè)獨(dú)立的線程可以用來(lái)顯示當(dāng)日的時(shí)間。如果用戶不希望用時(shí)鐘,線程被掛起。在任何情形下,掛起線程是很簡(jiǎn)單的,一旦掛起,重新啟動(dòng)線程也是一件簡(jiǎn)單的事。掛起、終止和恢復(fù)線程機(jī)制在Java2和早期版本中有所不同。盡管你運(yùn)用Java2的途徑編寫(xiě)代碼,仍需了解這些操作在早期Java環(huán)境下是如何完成的。例如,也許你需要更新或維護(hù)老的代碼,就需要了解為什么Java2會(huì)有這樣的變化。因?yàn)檫@些原因,下面內(nèi)容說(shuō)明了執(zhí)行線程控制的原始方法,接著是Java2的方法。先于Java2的版本(Java1.1或更早版本),程序用Thread定義的suspend()和resume()來(lái)暫停和再啟動(dòng)線程。它們的形式如下。finalvoidsuspend()finalvoidresume()Thread類(lèi)同樣定義了stop()來(lái)終止線程,其形式如下:voidstop()一旦線程被終止,它不能被resume()恢復(fù)繼續(xù)運(yùn)行。,Return,8.6.2Java2中的線程控制,在Java2中不能使用suspend(),resume()和stop()方法來(lái)控制線程,讀者也許會(huì)想那就沒(méi)有辦法來(lái)停止、恢復(fù)和結(jié)束線程,其實(shí)不然。相反,線程必須被設(shè)計(jì)成使用run()方法定期檢查來(lái)判定線程是否應(yīng)該被掛起,恢復(fù)或終止它自己的執(zhí)行。有代表性的,這由建立一個(gè)指示線程狀態(tài)的標(biāo)志變量來(lái)完成。只要該標(biāo)志設(shè)為“running”,run()方法必須繼續(xù)讓線程執(zhí)行。如果標(biāo)志設(shè)為“suspend”,線程必須暫停。若設(shè)為“stop”,線程必須終止。當(dāng)然,編寫(xiě)這樣的代碼有很多方法,但中心主題對(duì)所有的程序應(yīng)該是相同的。教材P216217頁(yè)的例子顯示了從Object繼承的wait()和notify()方法怎樣控制線程的執(zhí)行。該例與前面講過(guò)的程序很像。然而,不被贊同的方法都沒(méi)有用到。讓我們思考程序的執(zhí)行。NewTread類(lèi)包含了用來(lái)控制線程執(zhí)行的布爾型的實(shí)例變量suspendFlag。它被構(gòu)造函數(shù)初始化為false。Run()方法包含一個(gè)監(jiān)測(cè)suspendFlag的同步聲明的塊。如果變量是true,wait()方法被調(diào)用以掛起線程。Mysuspend()方法設(shè)置suspendFlag為true。Myresume()方法設(shè)置suspendFlag為false并且調(diào)用notify()方法來(lái)喚起線程。最后,main()方法被修改以調(diào)用mysuspend()和myresume()方法。,Return,8.6.3使用instanceof,最后,我們附帶介紹一下關(guān)鍵字instanceof。有時(shí),在運(yùn)行時(shí)間內(nèi)知道對(duì)象類(lèi)型是很有用的。例如,你有一個(gè)執(zhí)行線程生成各種類(lèi)型的對(duì)象,其他線程處理這些對(duì)象。這種情況下,讓處理線程在接受對(duì)象時(shí)知道每一個(gè)對(duì)象的類(lèi)型是大有裨益的。另一種在運(yùn)行時(shí)間內(nèi)知道對(duì)象的類(lèi)型是很有用的情形是強(qiáng)制類(lèi)型轉(zhuǎn)換。Java中非法強(qiáng)制類(lèi)型轉(zhuǎn)換導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。很多非法的強(qiáng)制類(lèi)型轉(zhuǎn)換在編譯時(shí)發(fā)生。然而包括類(lèi)層次結(jié)構(gòu)的強(qiáng)制類(lèi)型轉(zhuǎn)換可能是僅能在運(yùn)行時(shí)間里被察覺(jué)的非法強(qiáng)制類(lèi)型轉(zhuǎn)換。例如,一個(gè)名為A的父類(lèi)能生成兩個(gè)子類(lèi)B和C。這樣,在強(qiáng)制B對(duì)象轉(zhuǎn)換為類(lèi)型A或強(qiáng)制C對(duì)象轉(zhuǎn)換為類(lèi)型A都是合法的,但強(qiáng)制B對(duì)象轉(zhuǎn)換為C對(duì)象(或相反)都是不合法的。因?yàn)轭?lèi)型A的一個(gè)對(duì)象可以引用B或C。但是你怎么知道,在運(yùn)行時(shí),在強(qiáng)制轉(zhuǎn)換為C之前哪類(lèi)對(duì)象被引用?它可能是A、B或C的一個(gè)對(duì)象。如果它是B的對(duì)象,一個(gè)運(yùn)行時(shí)異常被引發(fā)。Java提供運(yùn)行時(shí)運(yùn)算符instanceof來(lái)解決這個(gè)問(wèn)題。instanceof運(yùn)算符具有下面的一般形式:objectinstanceoftype這里,object是類(lèi)的實(shí)例,而type是類(lèi)的類(lèi)型。如果object是指定的類(lèi)型或者可以被強(qiáng)制轉(zhuǎn)換成指定類(lèi)型,instanceof將它評(píng)估成true,若不是,則結(jié)果為false。這樣,instanceof是程序獲得對(duì)象運(yùn)行時(shí)類(lèi)型信息的方法。教材P218219頁(yè)的程序說(shuō)明了instanceof的應(yīng)用。,Return,

注意事項(xiàng)

本文(Java語(yǔ)言程序設(shè)計(jì)第08章.ppt)為本站會(huì)員(tia****nde)主動(dòng)上傳,裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。 若此文所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng)(點(diǎn)擊聯(lián)系客服),我們立即給予刪除!

溫馨提示:如果因?yàn)榫W(wǎng)速或其他原因下載失敗請(qǐng)重新下載,重復(fù)下載不扣分。




關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號(hào):ICP2024067431號(hào)-1 川公網(wǎng)安備51140202000466號(hào)


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺(tái),本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng),我們立即給予刪除!