版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第10章多線程《Java面向?qū)ο蟪绦蛟O(shè)計(jì)案例教程(第2版)》目錄/Contents10.110.210.3線程基礎(chǔ)與創(chuàng)建線程生命周期與操作線程同步與安全10.4
多線程性能優(yōu)化10.5
多線程實(shí)踐案例思政要點(diǎn)/Point團(tuán)隊(duì)合作
培養(yǎng)學(xué)生的團(tuán)隊(duì)合作精神和協(xié)同工作的能力,確保多線程環(huán)境中的有效溝通和協(xié)作。性能優(yōu)化
提升資源管理和優(yōu)化意識(shí),提高多線程系統(tǒng)的整體性能。信息安全
提升法律意識(shí)和信息安全意識(shí),確保多線程環(huán)境中的數(shù)據(jù)安全。創(chuàng)新思維
激發(fā)創(chuàng)新精神和持續(xù)學(xué)習(xí)的動(dòng)力,關(guān)注多線程技術(shù)的最新發(fā)展。線程基礎(chǔ)與創(chuàng)建10.1
線程就是在某種程度上相互隔離的、獨(dú)立運(yùn)行的程序。線程化是允許多個(gè)活動(dòng)共存于一個(gè)進(jìn)程的工具。大多數(shù)現(xiàn)代操作系統(tǒng)都支持線程,而且線程的概念以各種形式已存在了很多年。Java是第一個(gè)在語(yǔ)言本身中顯式地包含線程的主流編程語(yǔ)言,它沒有把線程化看作是底層操作系統(tǒng)工具。10.1.1線程的概念
每個(gè)Java程序都至少有一個(gè)線程——主線程。當(dāng)一個(gè)Java程序啟動(dòng)時(shí),JVM會(huì)創(chuàng)建主線程,并在該線程中調(diào)用程序的main()方法。JVM還創(chuàng)建了其他線程,但通常都看不到,例如與垃圾收集、對(duì)象中止和其他JVM內(nèi)務(wù)處理任務(wù)相關(guān)的線程。其他工具也創(chuàng)建線程,如抽象窗口工具包(AWT)或SwingUI工具包、Servlet容器、應(yīng)用程序服務(wù)器和遠(yuǎn)程方法調(diào)用(RMI)。圖10-1所示為線程全部運(yùn)行的狀態(tài)圖。10.1.2Java中的線程圖10-1
線程狀態(tài)轉(zhuǎn)化圖
使用線程的原因是它們可以使UI響應(yīng)更快、利用多處理系統(tǒng)、簡(jiǎn)化建模。執(zhí)行異步或后臺(tái)處理、響應(yīng)更快UI事件驅(qū)動(dòng)的UI工具箱(如AWT和Swing)有一個(gè)時(shí)間線程,它處理UI事件,如按鍵或鼠標(biāo)單擊。SWT和Swing程序把事件監(jiān)聽器與UI對(duì)象連接。當(dāng)特定事件(如單擊按鈕)發(fā)生時(shí),這些監(jiān)聽器會(huì)得到通知。事件監(jiān)聽器是AWT事件線程中調(diào)用的。
如果事件監(jiān)聽器要執(zhí)行持續(xù)很久的任務(wù),如檢查一個(gè)大文檔中的拼寫,事件線程將忙于運(yùn)行拼寫檢查器,所以在完成事件監(jiān)聽器之前,就不能處理額外的UI事件。這就會(huì)使程序看起來(lái)似乎停滯了,讓用戶不知所措。要避免使UI延遲響應(yīng),事件監(jiān)聽器應(yīng)該把較長(zhǎng)的任務(wù)放到另一個(gè)編程中,這樣AWT線程在任務(wù)的執(zhí)行過(guò)程中就可以繼續(xù)處理UI事件(包括取消正在執(zhí)行的長(zhǎng)時(shí)間運(yùn)行任務(wù)的請(qǐng)求)。10.1.3使用線程的原因線程創(chuàng)建10.2
繼承java.lang.Thread類,重寫publicvoidrun()方法。示例代碼如下:publicclassThread1extendsThread{//繼承Thread類并重寫run方法//該方法中重寫在當(dāng)前線程中需要運(yùn)行的代碼publicvoidrun(){for(inti=0;i<1000;i++){System.out.println(i);}}}10.2.1繼承java.lang.Thread類創(chuàng)建線程的第一種方式實(shí)現(xiàn)java.lang.Runnable接口,實(shí)現(xiàn)run()方法。代碼如下:publicclassRun1implementsRunnable{publicvoidrun(){for(inti=0;i<1000;i++){System.out.println(i);}}}
這種線程啟動(dòng)時(shí)和第一種方式不同,需要通過(guò)下面的代碼完成:Run1run1=newRun1();Threadt1=newThread(run1);t1.start();10.2.2實(shí)現(xiàn)java.lang.Runnable接口創(chuàng)建線程的第二種方式線程的生命周期10.310.3.1創(chuàng)建和就緒狀態(tài)
當(dāng)我們用new運(yùn)算符以后,就創(chuàng)建了一個(gè)線程的實(shí)例,創(chuàng)建完成以后該線程就處于新建狀態(tài),此時(shí)它就被Java虛擬機(jī)分配內(nèi)存,并且會(huì)初始化其成員變量的值。此時(shí)線程只是處于實(shí)例狀態(tài),并不會(huì)執(zhí)行線程體。當(dāng)線程對(duì)象調(diào)用了start()方法之后,該線程就處于就緒狀態(tài),Java虛擬機(jī)會(huì)為其創(chuàng)建方法調(diào)用的棧,但是該線程只是處于就緒狀態(tài),并不會(huì)開始執(zhí)行,只是代表該線程可以運(yùn)行了,至于何時(shí)運(yùn)行,取決于JVM里調(diào)度器的調(diào)度。10.3.2運(yùn)行和阻塞狀態(tài)
當(dāng)一個(gè)線程開始運(yùn)行后,它不可能一直處于運(yùn)行狀態(tài),線程在運(yùn)行過(guò)程中需要被中斷,目的是讓其他線程獲得執(zhí)行的機(jī)會(huì)。線程調(diào)度的細(xì)節(jié)取決于底層調(diào)度策略,系統(tǒng)會(huì)為每個(gè)線程分配一個(gè)微小的時(shí)間片段來(lái)處理任務(wù),當(dāng)時(shí)間用完后,系統(tǒng)會(huì)剝奪該線程所占用的資源,給其他線程執(zhí)行的機(jī)會(huì),至于下一個(gè)讓哪個(gè)線程執(zhí)行,會(huì)考慮線程的優(yōu)先級(jí)。當(dāng)出現(xiàn)下面的情況時(shí),線程會(huì)進(jìn)入阻塞狀態(tài)。1.線程調(diào)用了sleep()方法。2.線程調(diào)用了一個(gè)阻塞的I/O方法,在該方法返回之前,線程被阻塞。3.線程在等待某個(gè)通知(notify)。
程序調(diào)用了線程的suspend()方法,將該線程掛起。10.3.3線程死亡
線程出現(xiàn)以下幾種情況就會(huì)自動(dòng)結(jié)束,結(jié)束后的線程處于死亡狀態(tài)。1.?run()方法執(zhí)行完成,線程正常結(jié)束。2.線程出現(xiàn)了Exception或Error。3.直接調(diào)用了線程的stop()方法結(jié)束線程。如果想測(cè)試某個(gè)線程是否已經(jīng)死亡,則可以調(diào)用線程的isAlive()方法。當(dāng)線程處于就緒、運(yùn)行、阻塞狀態(tài)時(shí),該方法將返回true;當(dāng)線程處于新建、死亡狀態(tài)時(shí),該方法返回false。線程操作10.410.4.1join線程publicclassJoinThreadDemoextendsThread{//設(shè)置線程名publicJoinThreadDemo(Stringname){super(name);}//線程體publicvoidrun(){for(inti=0;i<100;i++){System.out.println(getName()+":"+i);}}publicstaticvoidmain(String[]args){//主線程開始for(inti=0;i<100;i++){if(i==20){//子線程被創(chuàng)建join線程使用示例JoinThreadDemodemo=newJoinThreadDemo("子線程被創(chuàng)建");try{//子線程就緒demo.start();//子線程加入主線程demo.join();}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}//顯示當(dāng)前線程名System.out.println(Thread.currentThread().getName()+":"+i);}}}10.4.2后臺(tái)線程1.后臺(tái)線程會(huì)隨著主線程的結(jié)束而結(jié)束,但是前臺(tái)線程不會(huì)。或者說(shuō),只要一個(gè)前臺(tái)進(jìn)程未退出,進(jìn)程就不會(huì)終止。2.默認(rèn)情況下,程序員創(chuàng)建的線程是用戶線程。用setDaemon(true)可以設(shè)置線程為后臺(tái)線程。而用isDaemon()可以判斷一個(gè)線程是前臺(tái)線程還是后臺(tái)線程。3.?JVM的垃圾回收器其實(shí)就是一個(gè)后臺(tái)線程。4.?setDaemon()方法必須在start方法之前設(shè)定,否則會(huì)拋出IllegalThreadStateExcetion異常。后臺(tái)線程的特點(diǎn)10.4.3線程睡眠1.?staticvoidsleep(longmillis):讓當(dāng)前正在執(zhí)行的線程暫停millis(毫秒),并且進(jìn)入阻塞狀態(tài)。該方法受到系統(tǒng)計(jì)時(shí)器和線程調(diào)度器的精度和準(zhǔn)確度的影響。2.staticvoidsleep(longmillis,intnanos):讓當(dāng)前正在執(zhí)行的線程暫停millis(毫秒)加nanos(微秒),并進(jìn)入阻塞狀態(tài)。這種過(guò)于精確的控制方法一般很少使用。當(dāng)線程調(diào)用sleep()方法進(jìn)入阻塞狀態(tài)后,在其休眠時(shí)間段內(nèi),該線程不會(huì)獲得執(zhí)行的機(jī)會(huì),即使系統(tǒng)中沒有其他可執(zhí)行的線程,處于sleep()中的線程也不會(huì)執(zhí)行。因此,sleep方法常用來(lái)暫停線程的執(zhí)行。sleep()兩種重載形式10.4.4線程讓步Thread.yield()方法的作用是:暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。yield()應(yīng)該做的是讓當(dāng)前運(yùn)行線程回到可運(yùn)行狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線程獲得運(yùn)行機(jī)會(huì)。因此,使用yield()的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)剌嗈D(zhuǎn)執(zhí)行。但是,實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€程還有可能被線程調(diào)度程序再次選中。10.4.5線程優(yōu)先級(jí)線程存在優(yōu)先級(jí),優(yōu)先級(jí)范圍為1~10。JVM線程調(diào)度程序是基于優(yōu)先級(jí)的搶先調(diào)度機(jī)制。在大多數(shù)情況下,當(dāng)前運(yùn)行的線程優(yōu)先級(jí)將大于或等于線程池中任何線程的優(yōu)先級(jí)。當(dāng)線程池中的線程都具有相同的優(yōu)先級(jí)時(shí),調(diào)度程序的JVM實(shí)現(xiàn)自由選擇它喜歡的線程。這時(shí)候調(diào)度程序的操作有兩種可能:一種是選擇一個(gè)線程運(yùn)行,直到它阻塞或者運(yùn)行完成為止;另一種是時(shí)間分片,為線程池內(nèi)的每個(gè)線程提供均等的運(yùn)行機(jī)會(huì)。線程默認(rèn)的優(yōu)先級(jí)是創(chuàng)建它的執(zhí)行線程的優(yōu)先級(jí)。可以通過(guò)setPriority(intnewPriority)更改線程的優(yōu)先級(jí)。例如:MyThreadt=newMyThread();t.setPriority(8);t.start();10.4.5線程優(yōu)先級(jí)
線程優(yōu)先級(jí)為1~10的正整數(shù)。JVM從不會(huì)改變一個(gè)線程的優(yōu)先級(jí)。然而,1~10的值是沒有保證的。一些JVM可能不識(shí)別10個(gè)不同的值,而將這些優(yōu)先級(jí)進(jìn)行每?jī)蓚€(gè)或多個(gè)合并,變成少于10個(gè)優(yōu)先級(jí),則兩個(gè)或多個(gè)優(yōu)先級(jí)的線程可能被映射為一個(gè)優(yōu)先級(jí)。線程的默認(rèn)優(yōu)先級(jí)是5。Thread類中有三個(gè)常量定義線程優(yōu)先級(jí)范圍:1.staticintMAX_PRIORITY:線程可以具有的最高優(yōu)先級(jí)。2.staticintMIN_PRIORITY:線程可以具有的最低優(yōu)先級(jí)。?staticintNORM_PRIORITY:線程的默認(rèn)優(yōu)先級(jí)。線程同步10.510.5.1線程安全機(jī)制
多線程可以共享資源(文件、數(shù)據(jù)庫(kù)、內(nèi)存等)。當(dāng)線程以并發(fā)模式訪問(wèn)共享數(shù)據(jù)時(shí),共享數(shù)據(jù)可能會(huì)發(fā)生沖突。Java引入了線程同步的概念,以實(shí)現(xiàn)共享數(shù)據(jù)的一致性。線程同步機(jī)制能使多個(gè)線程有序地訪問(wèn)共享資源,而不是同時(shí)操作共享資源。
在線程異步模式的情況下,如果同一時(shí)刻有一個(gè)線程A在修改共享數(shù)據(jù),另一個(gè)線程B在讀取共享數(shù)據(jù),當(dāng)線程A沒有處理完畢時(shí),線程B肯定會(huì)得到錯(cuò)誤的結(jié)果。如果采用多線程的同步控制機(jī)制,線程B會(huì)等待線程A修改完成后再進(jìn)行數(shù)據(jù)讀取。
鎖機(jī)制的實(shí)現(xiàn)方式是在共享代碼之前加入synchronized關(guān)鍵字。synchronized關(guān)鍵字可以修飾方法,也可以修飾變量。10.5.1線程安全機(jī)制
同步方法的語(yǔ)法格式如下。
class類名{publicsynchronized類型名稱方法名稱({....}}對(duì)于同步塊,synchronized獲取的是參數(shù)中的對(duì)象鎖,格式如下。
synchronized(obj){......}
當(dāng)線程執(zhí)行到同步塊時(shí),必須獲取obj對(duì)象的鎖才能執(zhí)行同步塊;否則線程只能等待獲得鎖。值得注意的是,obj對(duì)象的作用范圍不同,控制情況也不盡相同。偽代碼示例如下。publicvoidmethod(){Objectobj=new0bject();//創(chuàng)建局部object類型對(duì)象objsynchronized(obj){//同步塊//....}}10.5.2線程并發(fā)演示
一對(duì)夫妻拿著相同的銀行卡號(hào)去銀行取錢,一人拿著存折,另一人拿著銀行卡。假如卡里有2000元錢,丈夫取了1500元,妻子在同一時(shí)間也取了1500元。如果取錢這段程序沒有進(jìn)行同步,也就是說(shuō)這兩個(gè)操作可以同時(shí)進(jìn)行,當(dāng)?shù)谝怀绦驁?zhí)行時(shí),還沒有把錢從卡里扣掉,妻子也可以從卡里取出1500元,即兩個(gè)人從一張卡里取出3000元,這就涉及線程安全問(wèn)題。如果這段代碼進(jìn)行同步,當(dāng)存折和卡對(duì)應(yīng)的同一賬戶被操作時(shí),其余的線程再想去操作,只能等待,等前一個(gè)線程執(zhí)行完畢,把錢從卡里扣除后,第二個(gè)線程再去操作,發(fā)現(xiàn)余額不足,錢就無(wú)法取出。例10-310.5.2線程并發(fā)演示
publicclassThreadTest{publicdoublemoney=2000;publicstaticvoidmain(String[]args){ThreadTestt=newThreadTest();t.qukuan();}
publicvoidqukuan(){MyThreadt1=newMyThread("丈夫",1500);MyThreadt2=newMyThread("妻子",1500);t1.start();t
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025山西長(zhǎng)治市人民醫(yī)院招聘碩士以上專業(yè)技術(shù)工作人員50人模擬筆試試題及答案解析
- 2025江蘇紫金信通人才科技有限公司招聘7人備考筆試試題及答案解析
- 2025中國(guó)中信金融資產(chǎn)國(guó)際控股有限公司社會(huì)招聘參考筆試題庫(kù)附答案解析
- 深度解析(2026)《GBT 26088-2010造船 推進(jìn)用水冷四沖程柴油機(jī)》(2026年)深度解析
- 深度解析(2026)《GBT 25964-2010石油和液體石油產(chǎn)品 采用混合式油罐測(cè)量系統(tǒng)測(cè)量立式圓筒形油罐內(nèi)油品體積、密度和質(zhì)量的方法》
- 2025江西吉安市泰和縣新睿人力資源服務(wù)有限公司面向社會(huì)招聘項(xiàng)目制人員5人備考筆試題庫(kù)及答案解析
- 深度解析(2026)《GBT 25890.9-2010軌道交通 地面裝置 直流開關(guān)設(shè)備 第7-3部分:直流牽引供電系統(tǒng)專用測(cè)量、控制和保護(hù)裝置 隔離電壓變送器和其他電壓測(cè)量設(shè)備》(2026年)深度解析
- 2025年大慶高新區(qū)公益性崗位招聘10人備考考試試題及答案解析
- 深度解析(2026)《GBT 25782-2010 1-萘酚》(2026年)深度解析
- 2026廣西桂林醫(yī)科大學(xué)人才招聘118人(第一批)考試備考題庫(kù)及答案解析
- 口服抗栓藥物相關(guān)消化道損傷防治專家共識(shí)(2021)解讀
- 敬老服務(wù)前臺(tái)工作總結(jié)
- 統(tǒng)編版(2024新版)七年級(jí)下冊(cè)歷史教材習(xí)題答案
- 《如何理解「銷售」》課件
- UL2239標(biāo)準(zhǔn)中文版-2019支持導(dǎo)管油管和電纜的硬件UL中文版標(biāo)準(zhǔn)
- 【初中道法】擁有積極的人生態(tài)度(課件)-2024-2025學(xué)年七年級(jí)道德與法治上冊(cè)(統(tǒng)編版2024)
- 六層住宅樓框架結(jié)構(gòu)施工方案
- TGDNAS 049-2024 脊髓神經(jīng)功能評(píng)估技術(shù)
- 地理主題10-1 影響工業(yè)區(qū)位的因素
- 2022年北京海淀初二(上)期末語(yǔ)文試卷及答案
- 國(guó)開電大可編程控制器應(yīng)用課程實(shí)驗(yàn)參考答案
評(píng)論
0/150
提交評(píng)論