版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第9講Java的多線程機(jī)制
一、程序、進(jìn)程與線程二、線程的狀態(tài)三、線程優(yōu)先級(jí)與調(diào)度四、多線程實(shí)現(xiàn)機(jī)制五、基本的線程控制
多線程是指同時(shí)存在幾個(gè)執(zhí)行體,按幾條不同的執(zhí)行路線共同工作的情況。
Java內(nèi)置對(duì)多線程的支持。一、程序、進(jìn)程與線程程序:一段靜態(tài)的代碼。進(jìn)程:是程序的一次動(dòng)態(tài)執(zhí)行過程,包括從代碼加載、執(zhí)行到執(zhí)行完畢的一個(gè)完整的產(chǎn)生、發(fā)展到消亡的過程。線程:是比進(jìn)程更小的執(zhí)行單位,一個(gè)進(jìn)程在執(zhí)行過程中,可以產(chǎn)生多個(gè)線程。即每個(gè)線程都是一個(gè)動(dòng)態(tài)的產(chǎn)生、存在和消亡的過程。多線程的優(yōu)勢(shì)減輕編寫交互頻繁、涉及面多的程序的困難.程序的吞吐量會(huì)得到改善.有多個(gè)處理器的系統(tǒng),可以并發(fā)運(yùn)行不同的線程.(否則,任何時(shí)刻只有一個(gè)線程在運(yùn)行)線程與進(jìn)程的區(qū)別多個(gè)進(jìn)程的內(nèi)部數(shù)據(jù)和狀態(tài)都是完全獨(dú)立的,而多線程是共享一塊內(nèi)存空間和一組系統(tǒng)資源,有可能互相影響.線程本身的數(shù)據(jù)通常只有寄存器數(shù)據(jù),以及一個(gè)程序執(zhí)行時(shí)使用的堆棧,所以線程的切換比進(jìn)程切換的負(fù)擔(dān)要小。多線程基本概念文件輸入輸出裝置各種系統(tǒng)資源數(shù)據(jù)區(qū)段程序區(qū)段只有一個(gè)地方在執(zhí)行文件輸入輸出裝置各種系統(tǒng)資源數(shù)據(jù)區(qū)段程序區(qū)段同時(shí)有數(shù)個(gè)地方在執(zhí)行傳統(tǒng)的進(jìn)程多線程的任務(wù)二、線程的狀態(tài)stop()或run()結(jié)束NewThread創(chuàng)建狀態(tài)NotRunnable不可運(yùn)行狀態(tài)Dead消亡狀態(tài)newThread()yield()start()stop()stop()Runnable運(yùn)行狀態(tài)sleep()suspend()wait()resume()notify()notifyAll()創(chuàng)建狀態(tài)(newThread)
由主線程創(chuàng)建線程對(duì)象
ThreadmyThread=newMyThreadClass();可運(yùn)行狀態(tài)(Runnable) ThreadmyThread=newMyThreadClass(); myThread.start();
滿足一定的調(diào)度條件時(shí),進(jìn)入Runnable狀態(tài)。不可運(yùn)行狀態(tài)(NotRunnable) 調(diào)用了sleep()方法;
調(diào)用了suspend()方法;
為等候一個(gè)條件變量,線程調(diào)用wait()方法;
輸入輸出流中發(fā)生線程阻塞;死亡狀態(tài)(Dead)
線程的終止一般可通過兩種方法實(shí)現(xiàn):自然撤消(線程執(zhí)行完)或是被停止(調(diào)用stop()方法)。三、線程優(yōu)先級(jí)與調(diào)度優(yōu)先級(jí):確保重要的或時(shí)間緊迫的線程即時(shí)運(yùn)行方法。調(diào)度:強(qiáng)制優(yōu)先與公平的方法。線程調(diào)度器:按照線程的優(yōu)先級(jí)決定應(yīng)調(diào)度哪些線程來執(zhí)行,具有高優(yōu)先級(jí)的線程會(huì)在較低優(yōu)先級(jí)的線程之前得到執(zhí)行。線程的調(diào)度是搶先式的,如果在當(dāng)前線程的執(zhí)行過程中,一個(gè)具有更高優(yōu)先級(jí)的線程進(jìn)入就緒狀態(tài),則這個(gè)高優(yōu)先級(jí)的線程立即被調(diào)度執(zhí)行。對(duì)優(yōu)先級(jí)相同的線程來說,調(diào)度將采用輪轉(zhuǎn)法。線程優(yōu)先級(jí)與調(diào)度線程優(yōu)先級(jí)用數(shù)字來表示,范圍從1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一個(gè)線程的缺省優(yōu)先級(jí)是5,即Thread.NORM_PRIORITY。我們可以通過下面方法獲得或改變線程的優(yōu)先級(jí)。
intgetPriority();voidsetPriority(intnewPriority);四、多線程實(shí)現(xiàn)機(jī)制Java的線程:通過java.lang.Thread類來實(shí)現(xiàn)。每個(gè)線程都是通過某個(gè)特定Thread對(duì)象的方法run()來完成其操作的,方法run()稱為線程體。構(gòu)造線程體的2種方法:定義一個(gè)線程類,它繼承類Thread并重寫其中的方法run();提供一個(gè)實(shí)現(xiàn)接口Runnable的類作為線程的目標(biāo)對(duì)象,在初始化一個(gè)Thread類或者Thread子類的線程對(duì)象時(shí),把目標(biāo)對(duì)象傳遞給這個(gè)線程實(shí)例,由該目標(biāo)對(duì)象提供線程體run()。創(chuàng)建多線程的方式1、Threadclass2、Runnableinterface1.publicclassmythreadextendsAppletimplementsRunnable(小應(yīng)用或已經(jīng)是某個(gè)類的子類時(shí))2.繼承類ThreadpublicclassmythreadextendsThread3.上述兩種方法中都可用類Thread產(chǎn)生線程的對(duì)象Threadnewthread;4.創(chuàng)建并啟動(dòng)線程
newthread=newThread(this);newthread.start();5.run方法是運(yùn)行線程的主體,啟動(dòng)線程時(shí),由java直接調(diào)用publicvoidrun()6.停止線程,由小應(yīng)用程序的stop調(diào)用線程的stopnewthread.stop()7sleep方法的作用,暫停線程的執(zhí)行,讓其它線程得到機(jī)會(huì),sleep要丟出異常,必須抓住.Try{sleep(100)}catch(InterruptedExceptione){}例:小應(yīng)用程序中不用Runnable接口仍然可以使用線程(不調(diào)用主類的方法和調(diào)用主類的方法)
importjava.applet.*;publicclassthreadextendsApplet{mythreadt1=newmythread();publicstart(){t1.start();}classmythreadextendsThread{publicvoidrun(){for(inti=0;i<4;i++)System.out.println(“”+i);{try{sleep(400);}catch(InteruptedExceptione){}}}7.2創(chuàng)建線程的方式publicclassmainclassextendsApplet{Ct1=newC(this);publicvoidinit(){t1.start();}publicvoidpaint(Graphicsg){g.drawString("Hello,java",10,50);}}classCextendsThread{ mainclassa; C(mainclassb) {a=b;} publicvoidrun() {while(true){a.repaint(); try{sleep(400);} catch(InterruptedExceptione){}}}isAlive:判斷線程目前是否正在執(zhí)行狀態(tài)中
if(newthread.isAlive())newthread.stop();resume:要求被暫停得線程繼續(xù)執(zhí)行
suspend:暫停線程的執(zhí)行
join:等待線程執(zhí)行完畢
thatThread.join();被等待的那個(gè)線程不結(jié)束,當(dāng)前線程就一直等待.yield:將執(zhí)行的權(quán)力交給其它線程,自己到隊(duì)列的最后等待.其它常用的方法某一時(shí)刻只有一個(gè)線程在執(zhí)行,調(diào)度策略為固定優(yōu)先級(jí)調(diào)度.newthread.setPriority(Thread.MIN_PRIORITY)級(jí)別有:MIN-PRIORITYNOM_PRIORITYMAX-PRIORITY自私的線程:有很高的優(yōu)先權(quán)的線程,不主動(dòng)睡眠或讓出處理器控制權(quán).線程的優(yōu)先權(quán)當(dāng)一個(gè)線程執(zhí)行完所有語(yǔ)句后就自動(dòng)終止,調(diào)用線程的stop()方法,也可以強(qiáng)制終止線程。如果希望線程正常終止,可采用標(biāo)記來使線程中的run()方法退出。publicclassXyzimplementsRunnable{privatebooleantimeToQuit=false;
publicvoidrun()
{while(!timeToQuit)
{…..}//cleanupbeforerun()ends;
}publicvoidstopRunning(){timeToQuit=true;}}publicclassControlThread{privateRunnabler=newXyz();privateThreadt=newThread(r);
publicvoidstartThread(){t.start();}
publivoidstopThread(){r.stopRunning();}}暫停線程的執(zhí)行等待條件滿足再執(zhí)行.下面的例子顯示線程的掛起和喚醒小應(yīng)用程序第一次開始時(shí),線程被啟動(dòng)瀏覽器改變頁(yè)面時(shí),小應(yīng)用程序的stop()方法被調(diào)用,線程被掛起.瀏覽器回到原來的頁(yè)面時(shí),線程被喚醒.publicvoidstart(){if(mythread==null) {mythread=newThread();mythread.start();}else{mythread.resume();}}publicvoidrun(){while(true){try{sleep(100);}catch(InterruptedExceptione){}}}publicvoidstop(){ mythread.suspend(); }.1.通過繼承類Thread構(gòu)造線程體classSimpleThreadextendsThread{publicSimpleThread(Stringstr){super(str);}publicvoidrun(){for(inti=0;i<10;i++){System.out.println(i+""+getName());try{sleep((int)(Math.random()*1000));}catch(InterruptedExceptione){}}System.out.println("DONE!"+getName());}}publicclassTwoThreadsTest{ publicstaticvoidmain(Stringargs[]){newSimpleThread("First").start();newSimpleThread("Second").start();}}2.通過接口構(gòu)造線程體importjava.applet.*;importjava.util.*;importjava.awt.*;publicclassClockextendsAppletimplementsRunnable{ThreadclockThread;publicvoidstart(){if(clockThread==null){clockThread=newThread(this,"ClockTime");clockThread.start();}}publicvoidrun(){while(clockThread!=null){repaint();try{clockThread.sleep(1000);}catch(InterruptedExceptione){}}}publicvoidpaint(Graphicsg){Datenow=newDate();g.drawString(now.getHours()+":"+now.getMinutes()+":"+now.getSeconds(),5,10);}publicvoidstop(){clockThread.stop();clockThread=null;}}兩種方法的比較使用Runnable接口 可以將CPU,代碼和數(shù)據(jù)分開,形成清晰的模型;
還可以從其他類繼承;
保持程序風(fēng)格的一致性。直接繼承Thread類 不能再?gòu)钠渌惱^承;
編寫簡(jiǎn)單,可以直接操縱線程,無需使用Thread.currentThread()。五、基本的線程控制終止線程線程執(zhí)行完其run()方法后,會(huì)自然終止。通過調(diào)用線程的實(shí)例方法stop()來終止線程。測(cè)試線程狀態(tài)可以通過Thread中的isAlive()方法來獲取線程是否處于活動(dòng)狀態(tài);線程由start()方法啟動(dòng)后,直到其被終止之間的任何時(shí)刻,都處于‘Alive’狀態(tài)。線程的暫停和恢復(fù)sleep(timeout)方法suspend()和resume()
可以由線程自身調(diào)用suspend()方法暫停自己,也可以由其它線程調(diào)用suspend()方法暫停其執(zhí)行,但是要恢復(fù)由suspend()方法掛起的線程,只能由其它線程來調(diào)用resume()方法。join()掛起當(dāng)前線程。掛起的時(shí)間或者為timeout毫秒,或者掛起當(dāng)前線程直至它所調(diào)用的線程終止。多線程問題---執(zhí)行的順序多個(gè)線程運(yùn)行時(shí),調(diào)度策略為固定優(yōu)先級(jí)調(diào)度.級(jí)別相同時(shí),由操作系統(tǒng)按時(shí)間片來分配下面給出的例子中,共運(yùn)行三個(gè)線程,它們做同樣的事,每次打印循環(huán)次數(shù)和自己的序列號(hào),運(yùn)行結(jié)果表明,它們并不是連續(xù)運(yùn)行的.在上例中如果給某個(gè)線程賦予較高的優(yōu)先權(quán),則發(fā)現(xiàn)這個(gè)進(jìn)程壟斷控制權(quán)
thread.setPriority(Thread.MAX_PRIORITY)7.3多線程問題//多個(gè)進(jìn)程運(yùn)行時(shí)執(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+">+MySerialNum);System.out.println("thread"+threadNum+"bye.");}}多線程問題---如何寫多線程1.分別定義不同的線程類,在各自的run方法中定義線程的工作
classmythread1extendsThread{publicvoidrun{….}}classmythread2extendsThread{publicvoidrun{….}}2.在主類中實(shí)例化各線程類,并啟動(dòng)線程.publicclassdemoextendsApplet{publicvoidinit(){mythreadt1=newmythread1();mythreadt2=newmythread2();t1.start();t2.start();}}多線程問題---線程間的通信線程間的通信可以用管道流,創(chuàng)建管道流:PipedInputStreampis=newPipedInputStream();PipedOutputStreampos=newPipedOutputStream(pis);或:PipedOutputStreampos=newPipedOutputStream();PipedInputStreampis=newPipedInputStream(pos);線程1PipedOutputStreamPipedInputStream輸出流outStream輸入流inStream線程2多線程問題---線程間的通信管道流不能直接讀寫PrintStreamp=newPrintStream(pos);p.println(“hello”);DataInputStreamd=newDataInputStream(pis);d.readLine();2.通過一個(gè)中間類來傳遞信息.線程2線程1中間類mssm.write(s)s=m.read()write()read()printStreamDataInputStream多線程問題--線程間的通信管道流可以連接兩個(gè)線程間的通信下面的例子里有兩個(gè)線程在運(yùn)行,一個(gè)往外輸出信息,一個(gè)讀入信息.將一個(gè)寫線程的輸出通過管道流定義為讀線程的輸入.outStream=newPipedOutputStream();inStream=newPipedInputStream(outStream);newWriter(outStream).start();newReader(inStream).start();
多線程問題--線程間的通信主類Pipethread輔類Writer線程類輔類Reader線程類管道流將數(shù)據(jù)寫到輸出流從流中讀數(shù)據(jù)輸入流作為參數(shù)傳給WriterWriter(outStream)7.4多線程問題--線程間的通信.publicclassPipethread{publicstaticvoidmain(Stringargs[]){PipethreadthisPipe=newPipethread();thisPcess();}publicvoidprocess(){PipedInputStreaminStream;PipedOutputStreamoutStream;PrintStreamprintOut;try{outStream=newPipedOutputStream(); inStream=newPipedInputStream(outStream); newWriter(outStream).start(); newReader(inStream).start();}catch(IOExceptione){}}}7.4多線程問題---線程間的通信classReaderextendsThread{privatePipedInputStreaminStream;//從中讀數(shù)據(jù)
publicReader(PipedInputStreami){inStream=i;}publicvoidrun(){Stringline;DataInputStreamd;booleanreading=true;try{d=newDataInputStream(inStream); while(reading&&d!=null){ try{line=d.readLine(); if(line!=null){ System.out.println(”Read:"+line);} elsereading=false; }catch(IOExceptione){}}catch(IOExceptione){System.exit(0);} try{Thread.sleep(4000);} catch(InterruptedExceptione){}}}7.4多線程問題--線程間的通信.classWriterextendsThread{privatePipedOutputStreamoutStream;//將數(shù)據(jù)輸出
privateStringmessages[]={"Monday","Tuesday","Wednsday", "Thursday","Friday:","Saturday:","Sunday:"};publicWriter(PipedOutputStreamo)
{outStream=o;}publicvoidrun()
{PrintStreamp=newPrintStream(outStream);for(inti=0;i<messages.length;i++){ p.println(messages[i]); p.flush(); System.out.println("WrIte:"+messages[i]);} p.close();p=null;}}多線程問題---資源協(xié)調(diào)1.數(shù)據(jù)的完整性線程1線程2線程10資源取過來加1后送回去withdrwal()withdrwal()透支余額變量多線程問題---資源協(xié)調(diào)對(duì)共享對(duì)象的訪問必須同步,叫做條件變量.Java語(yǔ)言允許通過監(jiān)視器(有的參考書稱其為管程)使用條件變量實(shí)現(xiàn)線程同步.監(jiān)視器阻止兩個(gè)線程同時(shí)訪問同一個(gè)條件變量.它的如同鎖一樣作用在數(shù)據(jù)上.線程1進(jìn)入withdrawal方法時(shí),獲得監(jiān)視器(加鎖);當(dāng)線程1的方法執(zhí)行完畢返回時(shí),釋放監(jiān)視器(開鎖),線程2的withdrawal方能進(jìn)入.withdrawal()線程1監(jiān)視器線程2多線程問題---資源協(xié)調(diào)用synchronized來標(biāo)識(shí)的區(qū)域或方法即為監(jiān)視器監(jiān)視的部分。一個(gè)類或一個(gè)對(duì)象由一個(gè)監(jiān)視器,如果一個(gè)程序內(nèi)有兩個(gè)方法使用synchronized標(biāo)志,則他們?cè)谝粋€(gè)監(jiān)視器管理之下.一般情況下,只在方法的層次上使用關(guān)鍵區(qū)readwrite監(jiān)視器線程1線程2多線程問題---資源協(xié)調(diào)此處給出的例子演示兩個(gè)線程在同步限制下工作的情況.classAccount{staticsintbalance=1000;//為什么用static?staticsintexpense=0;publicsynchronizedvoidwithdrawl(intamount){if(amount<=balanc
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 工作總結(jié)之大專生畢業(yè)總結(jié)報(bào)告
- 2024年加油站項(xiàng)目資金需求報(bào)告代可行性研究報(bào)告
- 2024年體外及體內(nèi)反搏裝置項(xiàng)目資金申請(qǐng)報(bào)告
- 銀行合規(guī)審查制度
- 《支配權(quán)與請(qǐng)求權(quán)》課件
- 《保險(xiǎn)經(jīng)紀(jì)人概況》課件
- 美術(shù)老師工作總結(jié)
- 特別評(píng)論:如何看待退平臺(tái)后企業(yè)與政府的關(guān)系,202412 -中誠(chéng)信
- 山西省臨汾市洪洞縣八校聯(lián)考2023-2024學(xué)年七年級(jí)上學(xué)期期末測(cè)試數(shù)學(xué)試卷(含解析)
- 八年級(jí)物理功率課件
- Unit2Section A 1a-2b課件2024-2025學(xué)年人教版英語(yǔ)九年級(jí)全冊(cè)
- 《經(jīng)濟(jì)思想史》全套教學(xué)課件
- 2.2大氣受熱過程-以新疆番茄為例課件高中地理人教版(2019)必修一
- office操作技巧手冊(cè)系列-excel
- 2023-2024學(xué)年全國(guó)小學(xué)二年級(jí)下語(yǔ)文人教版期末考試試卷(含答案解析)
- 新質(zhì)生產(chǎn)力賦能高質(zhì)量發(fā)展的邏輯理路、關(guān)鍵著力點(diǎn)與實(shí)踐路徑
- 微積分試卷及規(guī)范標(biāo)準(zhǔn)答案6套
- 國(guó)家開放大學(xué)電大??啤锻恋乩靡?guī)劃》2023-2024期末試題及答案試卷代 1308
- 獨(dú)家采購(gòu)協(xié)議合同書
- 2024年安徽省中考數(shù)學(xué)試卷(含答案)
- 晶種法制備多元金屬納米晶體及燃料電池中的構(gòu)效關(guān)系研究
評(píng)論
0/150
提交評(píng)論