第九章多線程技術(shù)_第1頁
第九章多線程技術(shù)_第2頁
第九章多線程技術(shù)_第3頁
第九章多線程技術(shù)_第4頁
第九章多線程技術(shù)_第5頁
已閱讀5頁,還剩29頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第九章多線程技術(shù)第九章多線程技術(shù)9.1多線程基本概念9.2創(chuàng)建線程的方式9.3改變線程狀態(tài)的方法9.4多線程問題9.1多線程基本概念線程概念線程與進程的區(qū)別線程的優(yōu)越性線程的狀態(tài)及轉(zhuǎn)換線程概念并發(fā)多任務(wù)的實現(xiàn)采用的是在操作系統(tǒng)(OS)級運行多個進程。由于各個進程擁有自己獨立的運行環(huán)境,進程間的耦合關(guān)系差,并發(fā)粒度過于粗糙,并發(fā)實現(xiàn)也不太容易。為提高計算機的并行效率提出了線程概念。如果把進程所占資源與進程中的運行代碼相分離,那么在一個地址空間中便可運行多個指令流,由此產(chǎn)生線程概念。一般說來,所謂線程,指程序中的一個單一的順序控制流。

線程與進程的區(qū)別圖1和圖2分別示意了把一個任務(wù)按2個并發(fā)進程和2個并發(fā)線程分解后的情況。各個進程是在自己獨有的地址空間內(nèi)執(zhí)行,不但寄存器和堆棧是獨有的,動態(tài)數(shù)據(jù)堆、靜態(tài)數(shù)據(jù)區(qū)和程序代碼也相互獨立。各線程為保持自己的控制流而獨有寄存器和堆棧,但由于兩線程從屬于同一進程,它們共享同一地址空間,所以動態(tài)堆、靜態(tài)數(shù)據(jù)區(qū)及程序代碼為各線程共享,所以線程的切換比進程切換的負擔要小。進程作為獨立的實體,它為線程提供運行的資源并構(gòu)成靜態(tài)環(huán)境。線程是處理機調(diào)度的基本單位。線程的優(yōu)越性快速的關(guān)聯(lián)切換

由于操作系統(tǒng)級的進程獨占自己的虛地址空間,調(diào)度進程時,系統(tǒng)必須交換地址空間,因而進程切換時間長。在同一程序內(nèi)的多個線程共享同一地址空間,因而能使線程快速切換。系統(tǒng)額外開銷小

對多個進程的管理(創(chuàng)建、調(diào)度等)有比較大的系統(tǒng)開銷。在需要動態(tài)創(chuàng)建新進程的應(yīng)用中,這種開銷比較顯著。而對線程的管理雖然也會有系統(tǒng)開銷,但比進程的小得多。通信很容易實現(xiàn)

為了實現(xiàn)協(xié)作,進程或線程之間需要進行數(shù)據(jù)交換。對于自動共享同一地址空間的各線程來說,所有的全局數(shù)據(jù)都可以訪問,因而不需要什么特殊手段就能自動實現(xiàn)數(shù)據(jù)共享。而進程之間的通信則要復(fù)雜得多。線程個數(shù)比進程個數(shù)多得多

許多多任務(wù)操作系統(tǒng)限制用戶進程總數(shù)。在多線程系統(tǒng)中,雖存在線程總數(shù)限額,但個數(shù)多得多(OS/2支持4096個線程)。線程的狀態(tài)及轉(zhuǎn)換新建(New):代表線程的對象已經(jīng)被初始化,但尚未運行run方法。就緒(Runnable):線程正在運行run方法,但這只說明線程目前處于的狀態(tài)。如果系統(tǒng)沒有能力抽出CPU執(zhí)行時間給線程,線程就“不執(zhí)行”,這里的“不執(zhí)行”不代表“阻塞”或“死亡”。運行(Running):線程獲得了CPU資源正在執(zhí)行任務(wù),將一直運行到結(jié)束,除非此時它自動放棄資源或有更加高優(yōu)先級的線程進入。阻塞(NotRunnable):線程是可以執(zhí)行的,但由于某些因素的阻礙處于停滯狀態(tài),系統(tǒng)排程器略過了應(yīng)給線程的CPU執(zhí)行時間。死亡(Dead):線程的正式結(jié)束方式,run方法執(zhí)行完畢并返回。線程的狀態(tài)及轉(zhuǎn)換newThread()NewThreadRunnablestart()NotRunnablestop()stop()Deadyield()stop()orrun()exit..suspend()sleep()wait()resume().9.2創(chuàng)建線程的方式為了創(chuàng)建一個新的線程,必須指明這個線程所要執(zhí)行的代碼,Java是通過類做到這一點的。作為一個面向?qū)ο蟮某绦蛟O(shè)計語言,Java提供了java.lang.Thread類來進行多線程編程。Java中實現(xiàn)線程主要有兩種方法。繼承Thread類,覆蓋方法run()實現(xiàn)Runnable接口繼承Thread類Thread類最重要的方法是run()方法,它為Thread類的start()方法所調(diào)用,并提供線程所要執(zhí)行的代碼。為了指定自己新的代碼,只需要覆蓋它即可,即在創(chuàng)建的Thread類的子類中重寫run(),加入線程所要執(zhí)行的代碼。該方法的步驟是:從Thread類派生一個類,覆蓋Thread類中的run方法,然后創(chuàng)建該子類的對象,再調(diào)用start方法啟動本線程。importjava.applet.*;publicclassthreadextendsApplet{mythreadt1=newmythread();publicinit(){t1.start();}classmythreadextendsThread{publicvoidrun(){for(inti=0;i<4;i++)System.out.println(“”+i);{try{sleep(400);}catch(InteruptedExceptione){}}}實現(xiàn)Runnable接口Runnable接口只有一個方法run(),可以通過聲明自己的類實現(xiàn)Runnable接口并提供這一方法,并將線程代碼寫入其中,就完成了這一部分的任務(wù)。但是Runnable接口并沒有任何對線程的支持,還必須創(chuàng)建Thread類的實例,這一點通過Thread類的構(gòu)造方法publicThread(Runnabletarget)來實現(xiàn)。publicclassControlThread{privateRunnabler=newXyz();privateThreadt=newThread(r);

publicvoidstartThread(){t.start();}

publivoidstopThread(){r.stopRunning();}}publicclassXyzimplementsRunnable{privatebooleantimeToQuit=false;

publicvoidrun()

{while(!timeToQuit){…..}}publicvoidstopRunning(){timeToQuit=true;}}9.3改變線程狀態(tài)的方法start():

啟動線程run():

運行線程的主體,啟動線程時,由java直接調(diào)用stop():

停止線程sleep():

暫停線程的執(zhí)行,讓其它線程得到機會,sleep要丟出異常,必須抓住isAlive():判斷線程目前是否正在執(zhí)行狀態(tài)中resume():要求被暫停得線程繼續(xù)執(zhí)行suspend():暫停線程的執(zhí)行join():等待線程執(zhí)行完畢yield():將執(zhí)行的權(quán)力交給其它線程,自己到隊列的最后等待9.4多線程問題執(zhí)行的順序如何寫多線程線程間的通信資源協(xié)調(diào)daemon線程執(zhí)行的順序classmultithreadextendsThread{intthreadNum;publicstaticvoidmain(Stringargs[]){multithreadarray[]=newmultithread[3];for(inti=0;i<3;i++)array[i]=newmultithread(i);for(inti=0;i<3;i++)array[i].start();}

multithread(intSerialNum){super();threadNum=SerialNum;}

publicvoidrun(){for(intj=0;j<5;j++) System.out.println("<"+j+">"+threadNum);System.out.println("thread"+threadNum+"bye.");}}第一次第二次執(zhí)行的順序多個線程運行時,調(diào)度策略為固定優(yōu)先級調(diào)度.級別相同時,由操作系統(tǒng)按時間片來分配。上面面給出的例子中,共運行三個線程,它們做同樣的事,每次打印循環(huán)次數(shù)和自己的序列號,由結(jié)果可以看出某一時刻只有一個線程在執(zhí)行,多線程的執(zhí)行順序是交錯的、不連續(xù)的。Java中對于線程的優(yōu)先級可以進行如下設(shè)置:級別:MIN-PRIORITYNOM_PRIORITYMAX-PRIORITY執(zhí)行的順序classmultithreadextendsThread{intthreadNum;publicstaticvoidmain(Stringargs[]){multithreadarray[]=newmultithread[3];for(inti=0;i<3;i++)array[i]=newmultithread(i);array[1].setPriority(Thread.MAX_PRIORITY);for(inti=0;i<3;i++)array[i].start();}multithread(intSerialNum){super();threadNum=SerialNum;}publicvoidrun(){for(intj=0;j<5;j++) System.out.println("<"+j+">"+threadNum);System.out.println("thread"+threadNum+"bye.");}}第一次第二次如何寫多線程1.分別定義不同的線程類,在各自的run方法中定義線程的工作

classmythread1extendsThread{publicvoidrun{….}}classmythread2extendsThread{publicvoidrun{….}}2.在主類中實例化各線程類,并啟動線程.publicclassdemoextendsApplet{publicvoidinit(){mythreadt1=newmythread1();mythreadt2=newmythread2();t1.start();t2.start();}}線程間的通信管道流線程1PipedOutputStreamPipedInputStream輸出流outStream輸入流inStream線程2線程2線程1中間類mssm.write(s)s=m.read()write()read()中間類資源協(xié)調(diào)數(shù)據(jù)的完整性等待同步數(shù)據(jù)死鎖問題數(shù)據(jù)的完整性銀行卡副卡存折銀行取過來減1000后送回去getmoney()getmoney()透支存款額存款額23數(shù)據(jù)的完整性getmoney()線程1監(jiān)視器線程2線程1進入withdrawal方法時,獲得監(jiān)視器(加鎖);當線程1的方法執(zhí)行完畢返回時,釋放監(jiān)視器(開鎖),線程2的withdrawal方能進入.對共享對象的訪問必須同步,叫做條件變量.Java語言允許通過監(jiān)視器(有的參考書稱其為管程)使用條件變量實現(xiàn)線程同步.監(jiān)視器阻止兩個線程同時訪問同一個條件變量.它的如同鎖一樣作用在數(shù)據(jù)上.24數(shù)據(jù)的完整性用synchronized來標識的區(qū)域或方法即為監(jiān)視器監(jiān)視的部分,稱為關(guān)鍵區(qū)。如果一個程序內(nèi)有兩個方法使用synchronized標志,則他們在一個監(jiān)視器管理之下.一般情況下,只在方法的層次上使用關(guān)鍵區(qū)readwrite監(jiān)視器線程1線程2classAccount{staticsintstore=10000;//為什么用static?staticsintexpense=0;publicsynchronizedvoidgetmoney(intamount){if(amount<=store){store-=amount;expense+=amount;}else{System.out.println(“bounced:“+amount);}}等待同步數(shù)據(jù)生產(chǎn)者消費者..共享對象writeread可能出現(xiàn)的問題:生產(chǎn)者比消費者快時,消費者會漏掉一些數(shù)據(jù)沒有取到消費者比生產(chǎn)者快時,消費者取相同的數(shù)據(jù).notify()和wait()方法用來協(xié)調(diào)讀取的關(guān)系.notify()和wait()都只能從同步方法中的調(diào)用.notify的作用是喚醒正在等待同一個監(jiān)視器的線程.wait的作用是讓當前線程等待classMessageBoard{ privateStringmessage; privatebooleanready=false;//(信號燈) publicsynchronizedStringread() { while(ready==false) { try{wait();} catch(InterruptedExceptione){} } ready=false; notify();//起始狀態(tài)先寫后讀

returnmessage; } publicsynchronizedvoidwrite(Strings) { while(ready==true) { try{wait();} catch(InterruptedExceptione){} } message=s;ready=true;notify(); }}classReaderextendsThread{ privateMessageBoardmBoard; publicReader(MessageBoardm) {mBoard=m;} publicvoidrun(){ Strings=""; booleanreading=true; while(reading) { s=mBoard.read(); System.out.println("Readerread:"+s); if(s.equals("logoff"))reading=false;} System.out.println("Finished:10seconds..."); try{sleep(10000);} catch(InterruptedExceptione){} }}classWriterextendsThread{ privateMessageBoardmBoard; privateStringmessages[]={“1”,“.2”,“3”,”4”,”5”}; publicWriter(MessageBoardm) {mBoard=m;} publicvoidrun(){ for(inti=0;i<messages.length;i++) { mBoard.write(messages[i]); System.out.println("Writerwrote:"+messages[i]); try{ sleep((int)(Math.random()*100)); }catch(InterruptedExceptione){}} mBoard.write("logoff");}}}publicclassWaitNotifyDemo{publicstaticvoidmain(String[]args) { MessageBoardm=newMessageBoard(); Readerreadfrom_m=newReader(m); Writerwriteto_m=newWriter(m);

溫馨提示

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

最新文檔

評論

0/150

提交評論