Java08Java高級(jí)編程2多線程_第1頁(yè)
Java08Java高級(jí)編程2多線程_第2頁(yè)
Java08Java高級(jí)編程2多線程_第3頁(yè)
Java08Java高級(jí)編程2多線程_第4頁(yè)
Java08Java高級(jí)編程2多線程_第5頁(yè)
已閱讀5頁(yè),還剩43頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

最新文檔

評(píng)論

0/150

提交評(píng)論