Java08Java高級編程2多線程_第1頁
Java08Java高級編程2多線程_第2頁
Java08Java高級編程2多線程_第3頁
Java08Java高級編程2多線程_第4頁
Java08Java高級編程2多線程_第5頁
已閱讀5頁,還剩43頁未讀, 繼續免費閱讀

下載本文檔

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

文檔簡介

第9講Java的多線程機制

一、程序、進程與線程二、線程的狀態三、線程優先級與調度四、多線程實現機制五、基本的線程控制

多線程是指同時存在幾個執行體,按幾條不同的執行路線共同工作的情況。

Java內置對多線程的支持。一、程序、進程與線程程序:一段靜態的代碼。進程:是程序的一次動態執行過程,包括從代碼加載、執行到執行完畢的一個完整的產生、發展到消亡的過程。線程:是比進程更小的執行單位,一個進程在執行過程中,可以產生多個線程。即每個線程都是一個動態的產生、存在和消亡的過程。多線程的優勢減輕編寫交互頻繁、涉及面多的程序的困難.程序的吞吐量會得到改善.有多個處理器的系統,可以并發運行不同的線程.(否則,任何時刻只有一個線程在運行)線程與進程的區別多個進程的內部數據和狀態都是完全獨立的,而多線程是共享一塊內存空間和一組系統資源,有可能互相影響.線程本身的數據通常只有寄存器數據,以及一個程序執行時使用的堆棧,所以線程的切換比進程切換的負擔要小。多線程基本概念文件輸入輸出裝置各種系統資源數據區段程序區段只有一個地方在執行文件輸入輸出裝置各種系統資源數據區段程序區段同時有數個地方在執行傳統的進程多線程的任務二、線程的狀態stop()或run()結束NewThread創建狀態NotRunnable不可運行狀態Dead消亡狀態newThread()yield()start()stop()stop()Runnable運行狀態sleep()suspend()wait()resume()notify()notifyAll()創建狀態(newThread)

由主線程創建線程對象

ThreadmyThread=newMyThreadClass();可運行狀態(Runnable) ThreadmyThread=newMyThreadClass(); myThread.start();

滿足一定的調度條件時,進入Runnable狀態。不可運行狀態(NotRunnable) 調用了sleep()方法;

調用了suspend()方法;

為等候一個條件變量,線程調用wait()方法;

輸入輸出流中發生線程阻塞;死亡狀態(Dead)

線程的終止一般可通過兩種方法實現:自然撤消(線程執行完)或是被停止(調用stop()方法)。三、線程優先級與調度優先級:確保重要的或時間緊迫的線程即時運行方法。調度:強制優先與公平的方法。線程調度器:按照線程的優先級決定應調度哪些線程來執行,具有高優先級的線程會在較低優先級的線程之前得到執行。線程的調度是搶先式的,如果在當前線程的執行過程中,一個具有更高優先級的線程進入就緒狀態,則這個高優先級的線程立即被調度執行。對優先級相同的線程來說,調度將采用輪轉法。線程優先級與調度線程優先級用數字來表示,范圍從1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一個線程的缺省優先級是5,即Thread.NORM_PRIORITY。我們可以通過下面方法獲得或改變線程的優先級。

intgetPriority();voidsetPriority(intnewPriority);四、多線程實現機制Java的線程:通過java.lang.Thread類來實現。每個線程都是通過某個特定Thread對象的方法run()來完成其操作的,方法run()稱為線程體。構造線程體的2種方法:定義一個線程類,它繼承類Thread并重寫其中的方法run();提供一個實現接口Runnable的類作為線程的目標對象,在初始化一個Thread類或者Thread子類的線程對象時,把目標對象傳遞給這個線程實例,由該目標對象提供線程體run()。創建多線程的方式1、Threadclass2、Runnableinterface1.publicclassmythreadextendsAppletimplementsRunnable(小應用或已經是某個類的子類時)2.繼承類ThreadpublicclassmythreadextendsThread3.上述兩種方法中都可用類Thread產生線程的對象Threadnewthread;4.創建并啟動線程

newthread=newThread(this);newthread.start();5.run方法是運行線程的主體,啟動線程時,由java直接調用publicvoidrun()6.停止線程,由小應用程序的stop調用線程的stopnewthread.stop()7sleep方法的作用,暫停線程的執行,讓其它線程得到機會,sleep要丟出異常,必須抓住.Try{sleep(100)}catch(InterruptedExceptione){}例:小應用程序中不用Runnable接口仍然可以使用線程(不調用主類的方法和調用主類的方法)

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創建線程的方式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:判斷線程目前是否正在執行狀態中

if(newthread.isAlive())newthread.stop();resume:要求被暫停得線程繼續執行

suspend:暫停線程的執行

join:等待線程執行完畢

thatThread.join();被等待的那個線程不結束,當前線程就一直等待.yield:將執行的權力交給其它線程,自己到隊列的最后等待.其它常用的方法某一時刻只有一個線程在執行,調度策略為固定優先級調度.newthread.setPriority(Thread.MIN_PRIORITY)級別有:MIN-PRIORITYNOM_PRIORITYMAX-PRIORITY自私的線程:有很高的優先權的線程,不主動睡眠或讓出處理器控制權.線程的優先權當一個線程執行完所有語句后就自動終止,調用線程的stop()方法,也可以強制終止線程。如果希望線程正常終止,可采用標記來使線程中的run()方法退出。publicclassXyzimplementsRunnable{privatebooleantimeToQuit=false;

publicvoidrun()

{while(!timeToQuit)

{…..}//cleanupbeforerun()ends;

}publicvoidstopRunning(){timeToQuit=true;}}publicclassControlThread{privateRunnabler=newXyz();privateThreadt=newThread(r);

publicvoidstartThread(){t.start();}

publivoidstopThread(){r.stopRunning();}}暫停線程的執行等待條件滿足再執行.下面的例子顯示線程的掛起和喚醒小應用程序第一次開始時,線程被啟動瀏覽器改變頁面時,小應用程序的stop()方法被調用,線程被掛起.瀏覽器回到原來的頁面時,線程被喚醒.publicvoidstart(){if(mythread==null) {mythread=newThread();mythread.start();}else{mythread.resume();}}publicvoidrun(){while(true){try{sleep(100);}catch(InterruptedExceptione){}}}publicvoidstop(){ mythread.suspend(); }.1.通過繼承類Thread構造線程體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.通過接口構造線程體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,代碼和數據分開,形成清晰的模型;

還可以從其他類繼承;

保持程序風格的一致性。直接繼承Thread類 不能再從其他類繼承;

編寫簡單,可以直接操縱線程,無需使用Thread.currentThread()。五、基本的線程控制終止線程線程執行完其run()方法后,會自然終止。通過調用線程的實例方法stop()來終止線程。測試線程狀態可以通過Thread中的isAlive()方法來獲取線程是否處于活動狀態;線程由start()方法啟動后,直到其被終止之間的任何時刻,都處于‘Alive’狀態。線程的暫停和恢復sleep(timeout)方法suspend()和resume()

可以由線程自身調用suspend()方法暫停自己,也可以由其它線程調用suspend()方法暫停其執行,但是要恢復由suspend()方法掛起的線程,只能由其它線程來調用resume()方法。join()掛起當前線程。掛起的時間或者為timeout毫秒,或者掛起當前線程直至它所調用的線程終止。多線程問題---執行的順序多個線程運行時,調度策略為固定優先級調度.級別相同時,由操作系統按時間片來分配下面給出的例子中,共運行三個線程,它們做同樣的事,每次打印循環次數和自己的序列號,運行結果表明,它們并不是連續運行的.在上例中如果給某個線程賦予較高的優先權,則發現這個進程壟斷控制權

thread.setPriority(Thread.MAX_PRIORITY)7.3多線程問題//多個進程運行時執行順序是交叉的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.在主類中實例化各線程類,并啟動線程.publicclassdemoextendsApplet{publicvoidinit(){mythreadt1=newmythread1();mythreadt2=newmythread2();t1.start();t2.start();}}多線程問題---線程間的通信線程間的通信可以用管道流,創建管道流: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.通過一個中間類來傳遞信息.線程2線程1中間類mssm.write(s)s=m.read()write()read()printStreamDataInputStream多線程問題--線程間的通信管道流可以連接兩個線程間的通信下面的例子里有兩個線程在運行,一個往外輸出信息,一個讀入信息.將一個寫線程的輸出通過管道流定義為讀線程的輸入.outStream=newPipedOutputStream();inStream=newPipedInputStream(outStream);newWriter(outStream).start();newReader(inStream).start();

多線程問題--線程間的通信主類Pipethread輔類Writer線程類輔類Reader線程類管道流將數據寫到輸出流從流中讀數據輸入流作為參數傳給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;//從中讀數據

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;//將數據輸出

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;}}多線程問題---資源協調1.數據的完整性線程1線程2線程10資源取過來加1后送回去withdrwal()withdrwal()透支余額變量多線程問題---資源協調對共享對象的訪問必須同步,叫做條件變量.Java語言允許通過監視器(有的參考書稱其為管程)使用條件變量實現線程同步.監視器阻止兩個線程同時訪問同一個條件變量.它的如同鎖一樣作用在數據上.線程1進入withdrawal方法時,獲得監視器(加鎖);當線程1的方法執行完畢返回時,釋放監視器(開鎖),線程2的withdrawal方能進入.withdrawal()線程1監視器線程2多線程問題---資源協調用synchronized來標識的區域或方法即為監視器監視的部分。一個類或一個對象由一個監視器,如果一個程序內有兩個方法使用synchronized標志,則他們在一個監視器管理之下.一般情況下,只在方法的層次上使用關鍵區readwrite監視器線程1線程2多線程問題---資源協調此處給出的例子演示兩個線程在同步限制下工作的情況.classAccount{staticsintbalance=1000;//為什么用static?staticsintexpense=0;publicsynchronizedvoidwithdrawl(intamount){if(amount<=balanc

溫馨提示

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

評論

0/150

提交評論