第十章多線程_第1頁
第十章多線程_第2頁
第十章多線程_第3頁
第十章多線程_第4頁
第十章多線程_第5頁
已閱讀5頁,還剩53頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第十章多線程第一頁,共五十八頁,2022年,8月28日本講內容10.1線程的概念10.2Java中多線程的編程10.3線程的同步與死鎖第二頁,共五十八頁,2022年,8月28日10.1線程的概念1.程序、進程和線程

1>程序是為完成特定任務、用某種語言編寫的一組指令的集合。指一段靜態(tài)的代碼。2>進程是程序的一次執(zhí)行過程,是系統(tǒng)進行調度和資源分配的一個獨立單位。3>進程中的一小段程序代碼稱為線程。第三頁,共五十八頁,2022年,8月28日2.線程的主要特點:1>不能以一個文件名的方式獨立存在在磁盤中;不能單獨執(zhí)行,只有在進程啟動后才可啟動;各線程間共享進程空間的數(shù)據(jù)(代碼與數(shù)據(jù)).2>線程是比進程更小一級的執(zhí)行單元。3>一個進程在其執(zhí)行過程中,可以產(chǎn)生多個線程,形成多條執(zhí)行線索。4>每個線程也有它自身的產(chǎn)生、存在和消亡的過程,也是一個動態(tài)的概念。5>一個線程有它自己的入口和出口,以及一個順序執(zhí)行的序列6>線程不能獨立存在,必須存在于進程中,線程—線程創(chuàng)建、銷毀和切換的負荷遠小于進程,又稱為輕量級進程(lightweightprocess)。系統(tǒng)負擔小,主要是CPU的分配。第四頁,共五十八頁,2022年,8月28日3.進程進程是正在運行的一個程序程序:靜態(tài)對象--進程:動態(tài)過程操作系統(tǒng)為每個進程分配一段內存空間,包括:代碼、數(shù)據(jù)以及堆棧等資源多任務的操作系統(tǒng)(OS)中,進程切換對

CPU資源消耗較大第五頁,共五十八頁,2022年,8月28日4.多線程1>多線程是指同時存在幾個執(zhí)行體,按幾條不同的執(zhí)行線索共同工作的情況。2>多線程實現(xiàn)單個進程中的并發(fā)計算。3>各線程間共享進程空間的數(shù)據(jù),并利用這些共享單元來實現(xiàn)數(shù)據(jù)交換、實時通信與必要的同步操作。4>多線程的程序能更好地表述和解決現(xiàn)實世界的具體問題,是計算機應用開發(fā)和程序設計的一個必然發(fā)展趨勢。第六頁,共五十八頁,2022年,8月28日第七頁,共五十八頁,2022年,8月28日進程與多線程單線程多線程進程傳統(tǒng)進程多線程進程第八頁,共五十八頁,2022年,8月28日5.線程的調度調度策略時間片搶占式:高優(yōu)先級的線程搶占CPUJava的調度方法同優(yōu)先級線程組成先進先出隊列,使用時間片策略對高優(yōu)先級,使用優(yōu)先調度的搶占式策略12第九頁,共五十八頁,2022年,8月28日6.Java與多線程1>Java語言的一個重要功能特點:就是內置對多線程的支持,它使得編程人員可以很方便地開發(fā)出具有多線程功能,能同時處理多個任務的功能強大的應用程序。2>每個Java程序都有一個隱含的主線程每個Java程序都有一個主線程,對于APPLICATION程序,主線程是main()函數(shù)執(zhí)行的線索;對于Applet程序指揮瀏覽器加載并執(zhí)行Java小程序,要想實現(xiàn)多線程,必須在主線程中創(chuàng)建新的線程對象。3>線程的用途:利用它可以完成重復性的工作(如實現(xiàn)動畫、聲音等的播放);從事一次性較費時的初始化工作(如網(wǎng)絡連接、聲音數(shù)據(jù)文件的加載,但對圖像文件*.gif、*.jpeg在java中自動地在后臺載入、因而可不必設計圖像載入的線程);并行的執(zhí)行效果(一個進程多個線程)。第十頁,共五十八頁,2022年,8月28日6.線程的生命周期要想實現(xiàn)線程,必須在主線程中創(chuàng)建新的線程對象。Java語言使用Thread類及其子類的對象來表示線程,在它的一個完整的生命周期中通常要經(jīng)歷如下的五種狀態(tài):1>新建:當一個Thread類或其子類的對象被聲明并創(chuàng)建時,新生

的線程對象處于新建狀態(tài)2>就緒:處于新建狀態(tài)的線程被啟動后,將進入線程隊列等待CPU時間片,此時它已具備了運行的條件3>運行:當就緒的線程被調度并獲得處理器資源時,便進入運行狀態(tài),run()方法定義了線程的操作和功能4>阻塞:在某種特殊情況下,被人為掛起或執(zhí)行輸入輸出操作時,讓出CPU并臨時中止自己的執(zhí)行,進入阻塞狀態(tài)5>死亡:線程完成了它的全部工作或線程被提前強制性地中止stop()或destroy()線程死亡不具有繼續(xù)運行能力線程死亡有兩個原因:___正常執(zhí)行的線程完成它的全部工作,即執(zhí)行完run()方法的最后一句并退出___線程被強制終止,如stop()方法、destroy()方法第十一頁,共五十八頁,2022年,8月28日線程的生命周期第十二頁,共五十八頁,2022年,8月28日線程的生命周期(續(xù))Newborn:線程已創(chuàng)建,但尚未執(zhí)行Runnable:(就緒)線程已被調度,按優(yōu)先級和先到先服務原則在隊列中排隊等待CPU時間片資源Runnnig:正在運行Blocked:(阻塞)因某事件或睡眠而被暫時性地掛起Dead:正常/強行中斷,退出運行狀態(tài)第十三頁,共五十八頁,2022年,8月28日線程狀態(tài)新建狀態(tài)newThread(..)就緒狀態(tài)start()等待狀態(tài)執(zhí)行狀態(tài)I/Osleep()CPU調度run()結束stop()yield()消亡

I/O完成sleep時間到第十四頁,共五十八頁,2022年,8月28日Java對多線程的支持提供對多線程的支持Thread類start(),stop(),run()Runnable接口實現(xiàn)多線程的兩種編程方法繼承Thread類實現(xiàn)Runnable接口第十五頁,共五十八頁,2022年,8月28日Thread類Thread類綜合了Java程序中一個線程需要擁有的屬性和方法當生成一個Thread類的對象后,一個新的線程誕生了。每個線程都是通過目標對象的方法run()來完成其操作的。方法run()稱為線程體(線程方法)。提供線程體的目標對象是在初始化一個線程時指明的。任何實現(xiàn)了Runnable接口(實現(xiàn)run()方法)的類實例都可以作為線程的目標對象。第十六頁,共五十八頁,2022年,8月28日方法之一:繼承Thread類Thread類的重要方法:run()定義線程的具體操作系統(tǒng)調度此線程時自動執(zhí)行初始時無具體操作內容如何編程呢?-繼承Thread類,定義run()方法第十七頁,共五十八頁,2022年,8月28日Thread類java.lang包構造函數(shù)Thread();Thread(Stringthreadname);指定線程實例名線程的優(yōu)先級控制三個常量:

MAX_PRIORITY10;MIN_PRIORITY1;NORM_PRIORITY5;getPriority()返回線程優(yōu)先值

setPriority(intnewPriority)改變線程的優(yōu)先級線程創(chuàng)建時繼承父線程的優(yōu)先級第十八頁,共五十八頁,2022年,8月28日Thread類的有關方法voidstart():由Newborn到Runnable啟動線程StringgetName():返回線程的名稱run():線程在被調度時執(zhí)行的操作staticvoidsleep(指定時間毫秒):令當前活動線程在指定時間段內放棄對CPU控制,使其他線程有機會被執(zhí)行,時間到后重排隊產(chǎn)生例外InterruptedException用try塊調用sleep(),用catch塊處理例外第十九頁,共五十八頁,2022年,8月28日Thread類的有關方法(續(xù))suspend():掛起線程,處于阻塞狀態(tài)resume():恢復掛起的線程,重新進入就緒隊列排隊應用:可控制某線程的暫停與繼續(xù)方法:設一狀態(tài)變量suspendStatus=false(初始)暫停:if(!suspendStatus) {T.suspend();suspendStatus=true;}繼續(xù):if(suspendStatus) {T.resume();suspendStatus=false;}第二十頁,共五十八頁,2022年,8月28日Thread類的有關方法(續(xù))staticvoidyield():對正在執(zhí)行的線程若就緒隊列中有與當前線程同優(yōu)先級的排隊線程,則當前線程讓出CPU控制權,移到隊尾若隊列中沒有同優(yōu)先級的線程,忽略此方法stop():強制線程生命期結束booleanisAlive():返回boolean,表明是否線程還存在staticcurrentThread():返回當前線程

第二十一頁,共五十八頁,2022年,8月28日生成與運行線程–方法1MyThreadmt=newMyThread();mt.start();

classMyThreadextendsThread{publicvoidrun(){線程體…}}執(zhí)行run()方法第二十二頁,共五十八頁,2022年,8月28日建立線程線程控制(虛擬CPU)線程代碼被操作數(shù)據(jù)Thread類的子類的實例(mt)Thread類的子類提供的run方法Thread子類實例(mt)第二十三頁,共五十八頁,2022年,8月28日Thread類方法總結啟動線程:start()有關線程執(zhí)行的控制:stop()、suspend()、resume()有關調度控制Thread.sleep(10);//低優(yōu)先級的線程也可以獲得執(zhí)行Thread.yield();//同優(yōu)先級的線程可以獲得執(zhí)行suspend();//暫停本線程第二十四頁,共五十八頁,2022年,8月28日方法之二:RunnableRunnable接口自定義類實現(xiàn)Runnable接口使用Thread類的另一構造函數(shù):Thread(Runnable,String)用實現(xiàn)了Runnable接口的類的對象中所定義的run()方法,來覆蓋新創(chuàng)建的線程對象的run()方法使用start()啟動線程第二十五頁,共五十八頁,2022年,8月28日方法之二:Runnable(續(xù))例:classAimplementsRunnable{ publicvoidrun(){….}}classB{ publicstaticvoidmain(String[]arg){ Runnablea=newA(); Threadt=newThread(a); t.start(); } }第二十六頁,共五十八頁,2022年,8月28日建立線程例publicclassThreadTest{publicstaticvoidmain(String[]args){Job1j=newJob1();Threadt1=newThread(j);t1.start();}}classJob1implementsRunnable{inti=1;publicvoidrun(){while(i<50){System.out.println(i++);}}}第二十七頁,共五十八頁,2022年,8月28日建立線程線程控制(虛擬CPU)線程代碼被操作數(shù)據(jù)Thread的實例(t1)由實現(xiàn)了Runnable接口的類(Job1)提供—run方法實現(xiàn)Runnable接口的類(Job1)的實例(j)第二十八頁,共五十八頁,2022年,8月28日

生成與運行線程–方法2

classMyRunimplementsRunnable{publicvoidrun(){線程體…}}

MyRunmr=newMyRun();Threadt1=newThread(mr);t1.start();//Thread實例用于線程控制適合于:定義run()方法的類必須是其他類或其他類的子類。第二十九頁,共五十八頁,2022年,8月28日方法之二:Runnable(續(xù))兩種方法的選擇當需要從其他類,如Applet類繼承時,使用Runnable接口當編寫簡單的程序時,可考慮使用繼承Thread類例:RaceApplet.java具體運行結果(線程調度)與平臺有關第三十頁,共五十八頁,2022年,8月28日publicclassRunnerextendsThread{//賽跑者線程類

publicinttick=1;publicvoidrun(){while(tick<40000000)tick++;}}//Runner.java//RaceApplet是一個實現(xiàn)了多線程的AppletpublicclassRaceAppletextendsAppletimplementsRunnable{finalstaticintNUMRUNNERS=2;//定義賽跑線程的個數(shù)

finalstaticintSPACING=20;

//聲明兩個賽跑線程

Runner[]runners=newRunner[NUMRUNNERS];

//聲明一個畫圖線程

ThreadupdateThread=null;第三十一頁,共五十八頁,2022年,8月28日publicvoidinit(){//重載Applet的init()方法

for(inti=0;i<NUMRUNNERS;i++){runners[i]=newRunner();//創(chuàng)建賽跑線程線程

runners[i].setPriority(i+1);//設優(yōu)先級first=1,second=2}if(updateThread==null){

//創(chuàng)建繪圖線程,并設優(yōu)先級為3

updateThread=newThread(this,"ThreadRace");updateThread.setPriority(NUMRUNNERS+1);}addMouseListener(newMyAdapter());//注冊事件監(jiān)聽者}//endofinit()第三十二頁,共五十八頁,2022年,8月28日

//內部事件監(jiān)聽者類,監(jiān)聽鼠標事件classMyAdapterextendsMouseAdapter{

//鼠標點擊后,開始賽跑及繪制線程

publicvoidmouseClicked(MouseEventevt){if(!updateThread.isAlive())updateThread.start();//啟動繪制線程

for(inti=0;i<NUMRUNNERS;i++){if(!runners[i].isAlive())runners[i].start();//啟動賽跑線程}}}//endofclassMyAdapter第三十三頁,共五十八頁,2022年,8月28日publicvoidpaint(Graphicsg){//paint()方法中繪制框架

………}//endofpaint()//update()方法中繪制賽跑者的進度

publicvoidupdate(Graphicsg){for(inti=0;i<NUMRUNNERS;i++){//畫兩條線

g.drawLine(SPACING,(i+1)*SPACING,SPACING+(runners[i].tick)/100000,(i+1)*SPACING);}}//endofupdate()第三十四頁,共五十八頁,2022年,8月28日publicvoidrun(){//實現(xiàn)Runnable接口的run()方法

while(true){repaint();//重新繪制,自動調用update()方法

try{Thread.sleep(10);//休眠,把執(zhí)行機會讓給低優(yōu)先級線程}catch(InterruptedExceptione){}}}//endofrun()publicvoidstop(){//重載Applet的stop()方法

for(inti=0;i<NUMRUNNERS;i++){if(runners[i].isAlive())runners[i]=null;//中止賽跑線程}

if(updateThread.isAlive())updateThread=null;//中止繪圖線程}//endofstop()}//RaceApplet.java第三十五頁,共五十八頁,2022年,8月28日線程的同步與互斥問題的提出多個線程執(zhí)行的不確定性引起執(zhí)行結果的不穩(wěn)定

如線程A:A1-A2 線程B:B1-B2多個線程對內存、數(shù)據(jù)的共享,會造成操作的不完整性,會破壞數(shù)據(jù)。如push(a):i++;num[i]=a;pop():取出num[i];i--;第三十六頁,共五十八頁,2022年,8月28日線程的同步與互斥問題的解決同步:用synchronized關鍵字前綴給針對共享資源的操作加鎖;同步方法、同步塊

synchronizedvoidpush();synchronizedintpop();臨界區(qū)實現(xiàn)機制:管程第三十七頁,共五十八頁,2022年,8月28日線程的同步與互斥對象互斥鎖在Java中,每個對象有一個“互斥鎖”,該鎖可用來保證在同一時刻只能有一個線程訪問該對象。鎖的使用過程(當一個線程要操作一個對象時)準備加鎖對象是否已加鎖加鎖進入臨界區(qū)執(zhí)行操作解鎖否是第三十八頁,共五十八頁,2022年,8月28日線程的同步與互斥加鎖1(臨界區(qū)-方法)

synchronized方法名{…}進入該方法時加鎖加鎖2(臨界區(qū)-代碼塊)方法名{

….synchronized(this){…}//進入該代碼段時加鎖

….}一個線程為某對象加鎖后,便對該對象具有了監(jiān)控權。第三十九頁,共五十八頁,2022年,8月28日線程的同步與互斥線程間需協(xié)調與通訊:生產(chǎn)者/消費者問題進隊出隊生產(chǎn)者消費者第四十頁,共五十八頁,2022年,8月28日線程的同步與互斥wait()與notify()Object類的方法:publicfinalvoidwait():令當前線程掛起并放棄管程,同步資源解鎖,使別的線程可訪問并修改共享資源,而當前線程排隊等候再次對資源的訪問notify()喚醒正在排隊等待資源管程的線程中優(yōu)先級最高者,使之執(zhí)行并擁有資源的管程wait()+notify()+標志變量:可協(xié)調、同步不同線程的工作第四十一頁,共五十八頁,2022年,8月28日線程的同步與互斥主線程線程1()線程2()操作對象共享數(shù)據(jù)(隊)synchronized同步方法1(生產(chǎn))wait()notify()synchronized同步方法2(消費)wait()notify()第四十二頁,共五十八頁,2022年,8月28日線程的同步與互斥

publicfinalvoidwait()

方法在當前線程中調用方法:對象名.wait()使當前線程進入等待(某對象)狀態(tài),直到另一線程對該對象發(fā)出notify(或notifyAll)為止。調用方法的必要條件:當前線程必須具有對該對象的監(jiān)控權(加鎖)當前線程將釋放對象監(jiān)控權,然后進入等待隊列(wait隊列)。在當前線程被notify后,要重新獲得監(jiān)控權,然后從斷點處繼續(xù)代碼的執(zhí)行。第四十三頁,共五十八頁,2022年,8月28日線程的同步與互斥

publicfinalvoidnotify()

方法在當前線程中調用方法:對象名.notify()功能:喚醒等待該對象監(jiān)控權的一個線程。調用方法的必要條件:當前線程必須具有對該對象的監(jiān)控權(加鎖)

notifyAll()喚醒wait隊列中的所有線程,并把它門移入鎖申請隊列。第四十四頁,共五十八頁,2022年,8月28日線程狀態(tài)新建狀態(tài)就緒狀態(tài)start()等待狀態(tài)執(zhí)行狀態(tài)CPU調度run()結束消亡等待狀態(tài)對象wait()池等待狀態(tài)對象lock池wait()notify()synchronized()解鎖

sleep()join()yield()第四十五頁,共五十八頁,2022年,8月28日線程調度publicstaticvoidsleep(long

millis)

當前進程休眠指定時間publicstaticvoidyield()

主動讓出CPU,重新排隊正在執(zhí)行的線程將CPU讓給其他具有相同優(yōu)先級的線程,自己進入就緒狀態(tài)重新排隊publicfinalvoidjoin()

等待某線程結束第四十六頁,共五十八頁,2022年,8月28日等待另一線程結束Runnableot=newotheeThread();Threadtt=newThread(ot);tt.start();…//執(zhí)行自己的工作

try{tt.join();}catch(interruptedExceptione){}….//繼續(xù)做自己的事第四十七頁,共五十八頁,2022年,8月28日終止線程publicclassRimplementRunnable{privatebooleantimeToQuit=false;//設標記

publicvoidrun(){while(!timeToQuit){…}}publicvoidstopRunning(){timeToQuit=true;}}publicclasstest{publicstaticvoidmain(String[]args){Runnabler=newR();Threadt=newThread(r);t.start();if(…)r.stopRunning();}}第四十八頁,共五十八頁,2022年,8月28日線程的同步與互斥Wait_Notify程序CubbyHole.java創(chuàng)建用戶的線程子類Producer:產(chǎn)生數(shù)據(jù)(存數(shù)據(jù));Consumer:消費數(shù)據(jù)(取數(shù)據(jù))CubbyHole類,共享數(shù)據(jù)區(qū),同步方法put(intvalue)方法intget()方法主類中創(chuàng)建共享數(shù)據(jù)對象,并啟動兩線程第四十九頁,共五十八頁,2022年,8月28日classCubbyHole{privateintseq;//共享數(shù)據(jù)

privatebooleanavailable=false;//條件標志變量

publicsynchronizedintget(){//取數(shù)據(jù)的同步方法get() while(available==false){ try{ wait();//條件不符合,則wait }catch(InterruptedExceptione){} } available=false;//修改條件

notify();//通知喚醒其他等待管程的線程

returnseq;//返回要取出的數(shù)值}//endofget()第五十頁,共五十八頁,2022年,8月28日//存放數(shù)據(jù)的同步方法put()publicsynchronizedvoidput(intvalue){ while(available==true){ try{ wait();//條件不符合,則wait }catch(InterruptedExceptione){} } seq=value;//把共享變量修改為要放置的數(shù)據(jù)

available=true;//修改條件

notify();//通知喚醒其他等待管程的線程}//endofput()}//endofclassCubbyHole第五十一頁,共五十八頁,2022年,8月28日classProducerextendsThread{//生產(chǎn)者線程類

privateCubbyHolecubbyhole;privateintnumber;publicProducer(CubbyHolec,intnumber){cubbyhole=c;this.number=number;}publicvoidrun(){//定義run()方法

for(inti=0;i<10;i++){//共產(chǎn)生10個cubbyhole.put(i);

System.out.println("Producer#"+this.number+"put:"+i);try{sleep((int)(Math.random()*100));

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論