版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第10章Java多線程線程的生命周期2線程同步4Java多線程處理機(jī)制
31創(chuàng)建線程的方法33守護(hù)線程6線程聯(lián)合35本章內(nèi)容提要在程序設(shè)計(jì)中,經(jīng)常會(huì)遇到多個(gè)任務(wù)同時(shí)執(zhí)行的情況,這種資源被交替占用的任務(wù)執(zhí)行過(guò)程,被稱(chēng)為多線程處理,其中,每個(gè)任務(wù)一次動(dòng)態(tài)執(zhí)行過(guò)程被稱(chēng)為進(jìn)程。進(jìn)程執(zhí)行過(guò)程中的暫停被稱(chēng)為中斷。進(jìn)程通過(guò)中斷被分解成了若干段,每一段被稱(chēng)為一個(gè)線程。10.1Java多線程處理機(jī)制在Java語(yǔ)言的運(yùn)行環(huán)境中(JVM),內(nèi)置了一個(gè)線程調(diào)度器,用于確定某一時(shí)刻由哪一個(gè)線程占用計(jì)算機(jī)資源進(jìn)行執(zhí)行,從而實(shí)現(xiàn)了多線程操作。當(dāng)Java程序開(kāi)始運(yùn)行時(shí),main()方法首先執(zhí)行,此時(shí)線程調(diào)度器會(huì)開(kāi)啟一個(gè)線程,即為主線程(JavaApplet的主線程是Web瀏覽器),負(fù)責(zé)main()方法的執(zhí)行,除主線程之外的線程被稱(chēng)為其它線程。10.1Java多線程處理機(jī)制線程從最初的創(chuàng)建直至最后執(zhí)行的結(jié)束,需要遵循一個(gè)生命周期。利用生命周期,使得線程更加容易被分析和控制。線程的生命周期分為四個(gè)階段——新建、運(yùn)行、中斷、死亡。轉(zhuǎn)換過(guò)程如下圖:10.2線程的生命周期
圖10.1線程生命周期新建中斷運(yùn)行死亡等待隊(duì)列入隊(duì)出隊(duì)導(dǎo)致中斷中斷解除執(zhí)行結(jié)束1.新建線程對(duì)象定義后,線程直接進(jìn)入新建狀態(tài)。處于新建狀態(tài)的線程不占用計(jì)算機(jī)資源。2.運(yùn)行當(dāng)線程占用計(jì)算機(jī)資源時(shí),就進(jìn)入了運(yùn)行狀態(tài)。線程由新建狀態(tài)轉(zhuǎn)入運(yùn)行狀態(tài)并不是直接完成的,需要進(jìn)入一個(gè)由進(jìn)程調(diào)度器控制的等待隊(duì)列,等待計(jì)算機(jī)資源的閑置(被其它線程釋放),當(dāng)計(jì)算機(jī)資源閑置時(shí),依據(jù)隊(duì)列的先進(jìn)先出性,最先進(jìn)入等待隊(duì)列的線程最先出隊(duì),獲得計(jì)算機(jī)資源,轉(zhuǎn)入運(yùn)行狀態(tài)。
10.2線程的生命周期
3.中斷處于運(yùn)行狀態(tài)的線程必須在運(yùn)行一段時(shí)間后讓出計(jì)算機(jī)資源,這就是線程的中斷。中斷原因包括:阻塞線程調(diào)度器的控制通過(guò)sleep(longmill)方法通過(guò)wait()方法10.2線程的生命周期
當(dāng)線程中斷解除時(shí)(例如:通過(guò)Scanner類(lèi)的方法輸入了數(shù)據(jù)、經(jīng)過(guò)mill毫秒后休眠結(jié)束),線程并不會(huì)立刻返回運(yùn)行狀態(tài),而是重新進(jìn)入等待隊(duì)列進(jìn)行排隊(duì),并依據(jù)隊(duì)列先進(jìn)先出的使用原則,占用計(jì)算機(jī)資源,進(jìn)入運(yùn)行狀態(tài)。4.死亡線程執(zhí)行完畢后,就進(jìn)入了最后的死亡狀態(tài),線程的生命周期同時(shí)結(jié)束。10.2線程的生命周期
Java多線程的實(shí)現(xiàn)是通過(guò)創(chuàng)建線程對(duì)象開(kāi)始的。線程對(duì)象的創(chuàng)建有兩種方法——利用Thread類(lèi)的子類(lèi)創(chuàng)建線程和使用Runnable接口創(chuàng)建線程。兩種方法相比,第一種較為簡(jiǎn)單,第二種更加靈活。10.3創(chuàng)建線程的方法1.利用Thread類(lèi)的子類(lèi)創(chuàng)建線程Thread類(lèi)位于java.lang包中,是Java語(yǔ)言提供的線程類(lèi)。定義一個(gè)繼承Thread類(lèi)的子類(lèi),在該類(lèi)中重寫(xiě)Thread類(lèi)中的publicvoidrun()方法,當(dāng)子類(lèi)對(duì)象——線程對(duì)象獲得資源時(shí),會(huì)調(diào)用run()方法,執(zhí)行線程操作。
10.3創(chuàng)建線程的方法10.3創(chuàng)建線程的方法例10-1
classSimpleThreadextendsThread{publicvoidrun(){for(inti=0;i<3;i++){System.out.println(getName()+i);try{ sleep((int)(Math.random()*1000));}catch(InterruptedExceptione){System.out.println(e);}}System.out.println("DONE!"+getName());}}10.3創(chuàng)建線程的方法classExample10_1{publicstaticvoidmain(Stringargs[]){SimpleThreadone=newSimpleThread();one.setName("oneThread");one.start();
SimpleThreadtwo=newSimpleThread();two.setName("twoThread");two.start();}}2.使用Runnable接口對(duì)象創(chuàng)建線程利用Thread類(lèi)定義直接線程對(duì)象,此時(shí),調(diào)用的Thread類(lèi)的構(gòu)造方法需要設(shè)置一個(gè)對(duì)象做參數(shù),而定義該對(duì)象的類(lèi)必須實(shí)現(xiàn)java.lang.Runnable接口,這個(gè)對(duì)象被稱(chēng)為線程對(duì)象的目標(biāo)對(duì)象。Runnable接口中定義了publicvoidrun()方法,定義目標(biāo)對(duì)象的類(lèi)使用了Runnable接口,必須重寫(xiě)其中的publicvoidrun()方法。
10.3創(chuàng)建線程的方法例10-2
importjava.util.Date;importjava.awt.Graphics;publicclassExample10_2extendsjava.applet.AppletimplementsRunnable{ ThreadclockThread; publicvoidstart(){ if(clockThread==null){ clockThread=newThread(this,"Clock");
clockThread.start();}}10.3創(chuàng)建線程的方法publicvoidrun(){
while(clockThread!=null){ repaint();
try{ clockThread.sleep(1000); }catch(InterruptedExceptione){System.out.println(e);}
}}10.3創(chuàng)建線程的方法publicvoidpaint(Graphicsg){Datenow=newDate();
g.drawString(now.toString(),5,10);}publicvoidstop(){clockThread.stop();clockThread=null;}}10.3創(chuàng)建線程的方法3.線程常用操作方法publicvoidstart()使線程進(jìn)入等待隊(duì)列publicvoidrun()使線程進(jìn)入運(yùn)行狀態(tài)publicbooleanisAlive()判斷線程是否處于運(yùn)行狀態(tài)publicstaticvoidsleep(longmill)使正在運(yùn)行的線程休眠(中斷)mill毫秒publicstaticThreadcurrentThread()獲取正在運(yùn)行的線程對(duì)象publicvoidinterrupt()吵醒正在休眠的線程10.3創(chuàng)建線程的方法10.3創(chuàng)建線程的方法例10-3
publicclassThreadMethodimplementsRunnable{ ThreadliLei,fire,alarm; ThreadMethod(){ liLei=newThread(this); } publicvoidrun(){ longtime=0; while(true){ if(Thread.currentThread()==liLei){ System.out.println("李雷今天太累了,抽著煙睡著了......");
10.3創(chuàng)建線程的方法try{ fire=newThread(this); fire.start();
Thread.sleep(1000*60*60);
}catch(InterruptedExceptione){ System.out.println("李雷被報(bào)警聲叫醒了!"); errupt();
} return; }elseif(Thread.currentThread()==fire){ if(time==0){ System.out.println("李雷的煙頭點(diǎn)燃了地毯,李雷還在睡覺(jué)......");try{ fire=newThread(this); fire.start();
Thread.sleep(1000*60*60);
}catch(InterruptedExceptione){ System.out.println("李雷被報(bào)警聲叫醒了!"); errupt();
} return; }elseif(Thread.currentThread()==fire){ if(time==0){ System.out.println("李雷的煙頭點(diǎn)燃了地毯,李雷還在睡覺(jué)......");10.3創(chuàng)建線程的方法time=2000;try{ Thread.sleep(time); }catch(InterruptedExceptione){ System.out.println(e); }}elseif(time>0&&time<3000){ System.out.println("地毯著火了,李雷還沒(méi)醒?。?!"); time=4000; try{ Thread.sleep(time); }catch(InterruptedExceptione){ System.out.println(e); }10.3創(chuàng)建線程的方法10.3創(chuàng)建線程的方法}elseif(time>3000){ System.out.println("火勢(shì)越來(lái)越大......"); alarm=newThread(this); alarm.start();try{ Thread.sleep(time);}catch(InterruptedExceptione){ System.out.println("撲滅了地毯上的火,吸煙真是危險(xiǎn)?。?);return; } }}elseif(Thread.currentThread()==alarm){ System.out.println("報(bào)警器被觸發(fā)啦!");10.3創(chuàng)建線程的方法try{ Thread.sleep(500); }catch(InterruptedExceptione){ System.out.println(e); } liLerrupt(); return; } } }}classExample10_3{publicstaticvoidmain(String[]args){ ThreadMethodmethod=newThreadMethod(); method.liLei.start();}}10.3創(chuàng)建線程的方法4.多線程中的共享與獨(dú)享
當(dāng)多個(gè)線程使用同一個(gè)目標(biāo)對(duì)象時(shí),它們都將利用目標(biāo)對(duì)象所屬類(lèi)中重寫(xiě)的run()方法進(jìn)行線程的執(zhí)行。此時(shí),如果run()方法中使用了類(lèi)中的成員變量,那么該成員變量的操作對(duì)每個(gè)線程都是開(kāi)放的——目標(biāo)對(duì)象的成員變量被多個(gè)線程的訪問(wèn)共享。但是,對(duì)于run()方法中定義的局部變量,由于其是在每個(gè)線程調(diào)用run()方法時(shí)被分配內(nèi)存空間,調(diào)用結(jié)束后又立即釋放內(nèi)存空間,因此僅被每個(gè)線程的訪問(wèn)獨(dú)享。classSavingBoximplementsRunnable{ doublebalance;
publicvoidrun(){ intcount=0;
while(true){balance=balance+1000; count++; try{ System.out.println(Thread.currentThread().getName()+"第"+count+"次存錢(qián),存錢(qián)盒目前有"+balance+"元。"); if(count==3){System.out.println(Thread.currentThread().getName()+"存了"+count+"次,本月存錢(qián)結(jié)束。");10.3創(chuàng)建線程的方法return; } Thread.sleep(2000); }catch(InterruptedExceptione){ System.out.println(e); } } }}publicclassExample10_4{ publicstaticvoidmain(String[]args){ SavingBoxbox=newSavingBox(); ThreadliLei=newThread(box);
liLei.setName("李雷"); ThreadhanMeiMei=newThread(box); hanMeiMei.setName("韓梅梅"); liLei.start(); hanMeiMei.start(); }}10.3創(chuàng)建線程的方法使用相同目標(biāo)對(duì)象的線程會(huì)共享目標(biāo)對(duì)象的成員變量,有時(shí)這種情況需要避免,即當(dāng)一個(gè)線程訪問(wèn)共享成員變量時(shí),即使該線程因休眠而中斷,其它線程也需要等待,直到訪問(wèn)結(jié)束,其它線程才可以進(jìn)行訪問(wèn),這種情況被稱(chēng)為線程同步或線程級(jí)安全。要實(shí)現(xiàn)線程同步,需要使用synchronized關(guān)鍵字修飾共享成員變量的訪問(wèn)方法,這個(gè)方法被稱(chēng)為同步方法。10.4線程同步
同步方法中,sleep()方法的調(diào)用不會(huì)引起中斷。此時(shí),若想通過(guò)程序設(shè)計(jì)中斷同步,只能通過(guò)Thread類(lèi)中的wait()方法完成,而解除wait()方法的中斷需調(diào)用notifyAll()方法。notifyAll()方法會(huì)使所有因wait()方法調(diào)用而中斷的線程結(jié)束中斷,按“先中斷先入隊(duì)”的原則進(jìn)入等待隊(duì)列,等待資源的空閑,準(zhǔn)備從中斷位置繼續(xù)執(zhí)行。10.4線程同步
例10-5
classAccount{ doublebalance; publicsynchronizedvoiddeposit(doublemoney){
balance=balance+money; System.out.println("存入"+money+"元,賬戶(hù)余額"+balance+"元。"); try{ Thread.sleep(1000); }catch(InterruptedExceptione){ System.out.println(e); } notifyAll();
}10.4線程同步
publicsynchronizedvoidwithdraw(doublemoney){ while(balance<money){ System.out.println("賬戶(hù)余額不足,等待存款。"); try{ wait();
}catch(InterruptedExceptione){ System.out.println(e); } } balance=balance-money; System.out.println("取出"+money+"元,賬戶(hù)余額"+balance+"元。"); }}10.4線程同步
10.4線程同步
classSynchroTestimplementsRunnable{ ThreadliLei,hanMeiMei; Accountaccount; SynchroTest(){ liLei=newThread(this); hanMeiMei=newThread(this); account=newAccount(); } publicvoidrun(){ if(Thread.currentThread()==liLei){for(inti=1;i<=3;i++){System.out.println("李雷掙錢(qián),將工資悉數(shù)存入家庭銀行......"); account.deposit(1000); try{10.4線程同步
Thread.sleep(2000); }catch(InterruptedExceptione){ System.out.println(e); }}}elseif(Thread.currentThread()==hanMeiMei){for(inti=1;i<=3;i++){System.out.println("韓梅梅把握家中的開(kāi)支,從家庭銀行取錢(qián)......"); account.withdraw(800); } } }}publicclassExample10_5{ publicstaticvoidmain(String[]args){ SynchroTestsynchro=newSynchroTest(); synchro.liLei.start(); synchro.hanMeiMei.start(); }}當(dāng)一個(gè)線程正在運(yùn)行時(shí),可以與另一個(gè)線程進(jìn)行聯(lián)合,此時(shí),正在運(yùn)行的線程會(huì)中斷執(zhí)行,將計(jì)算機(jī)資源交給聯(lián)合的線程,直到聯(lián)合的線程運(yùn)行結(jié)束,才會(huì)結(jié)束中斷,進(jìn)入等待隊(duì)列排隊(duì),準(zhǔn)備獲取計(jì)算機(jī)資源,恢復(fù)運(yùn)行。線程對(duì)象調(diào)用join()方法,表示進(jìn)行線程聯(lián)合操作。由于join()方法聲明了InterruptedException異常,因此在方法調(diào)用位置需要進(jìn)行異常捕獲。例子10-6演示了線程聯(lián)合。
10.5線程聯(lián)合
例10-6
classThreadJoinTestimplementsRunnable{Threadtourist,policeOffice;ThreadJoinTest(){ tourist=newThread(this); tourist.setName("李雷");}publicvoidrun(){ if(Thread.currentThread()==tourist){ System.out.println("李雷計(jì)劃去國(guó)外旅游,需要先到警察局辦理護(hù)照!"); try{ Thread.sleep(1000);policeOffice=newThread(this); policeOffice.start();
policeOffice.join();
10.5線程聯(lián)合
}catch(InterruptedExceptione){ System.out.println(e); } System.out.println("李雷拿到了護(hù)照,可以去辦理簽證,準(zhǔn)備出國(guó)了。"); }elseif(Thread.currentThread()==policeOffice){ try{ System.out.println("李雷來(lái)到警察局正在填寫(xiě)申請(qǐng)表......"); Thread.sleep(1000); System.out.println("照相......"); Thread.sleep(1000); System.out.println("將申請(qǐng)表和照片交給警察審核......");10.5線程聯(lián)合
10.5線程聯(lián)合
Thread.sleep(1000); System.out.println("審核通過(guò),交款,15個(gè)工作日后領(lǐng)取護(hù)照!"); Thread.sleep(2000); }catch(InterruptedExceptione){System
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 舞蹈藝術(shù)之魅力
- 人事部在企業(yè)戰(zhàn)略中的角色計(jì)劃
- 感恩父母與愛(ài)同行的演講稿5篇
- 2024年員工三級(jí)安全培訓(xùn)考試題(滿分必刷)
- 2023-2024年項(xiàng)目安全培訓(xùn)考試題帶答案(奪分金卷)
- 社團(tuán)運(yùn)營(yíng)與成員發(fā)展
- 《本科心律失?!氛n件
- 教授能量轉(zhuǎn)換守恒
- 北師大版八年級(jí)下冊(cè)數(shù)學(xué)期末測(cè)試題
- 印刷設(shè)備智能化升級(jí)-第1篇-洞察分析
- 2024-2025學(xué)年七年級(jí)上學(xué)期歷史觀點(diǎn)及論述題總結(jié)(統(tǒng)編版)
- 2024年市特殊教育學(xué)校工作總結(jié)范文(2篇)
- 【MOOC】創(chuàng)新思維與創(chuàng)業(yè)實(shí)驗(yàn)-東南大學(xué) 中國(guó)大學(xué)慕課MOOC答案
- 青島大學(xué)《英語(yǔ)綜合》2023-2024學(xué)年第一學(xué)期期末試卷
- 課題1 金屬材料 教學(xué)設(shè)計(jì) 九年級(jí)化學(xué)下冊(cè)人教版2024
- EPC工程總承包實(shí)施方案
- 新人模特經(jīng)紀(jì)合同范例
- 電動(dòng)車(chē)自燃應(yīng)急預(yù)案
- 語(yǔ)法辨析-中考語(yǔ)文真題題源解密(遼寧版)(帶答案)
- 山西省晉中市2023-2024學(xué)年高一上學(xué)期期末考試 化學(xué) 含解析
- 2024-2030年中國(guó)電子駐車(chē)制動(dòng)器(EPB)行業(yè)發(fā)展現(xiàn)狀及前景趨勢(shì)研究報(bào)告
評(píng)論
0/150
提交評(píng)論