Java程序設(shè)計(jì)教程課件第10章 Java多線程_第1頁(yè)
Java程序設(shè)計(jì)教程課件第10章 Java多線程_第2頁(yè)
Java程序設(shè)計(jì)教程課件第10章 Java多線程_第3頁(yè)
Java程序設(shè)計(jì)教程課件第10章 Java多線程_第4頁(yè)
Java程序設(shè)計(jì)教程課件第10章 Java多線程_第5頁(yè)
已閱讀5頁(yè),還剩34頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論