《基于任務驅動模式的Java程序設計》課件第七章_第1頁
《基于任務驅動模式的Java程序設計》課件第七章_第2頁
《基于任務驅動模式的Java程序設計》課件第七章_第3頁
《基于任務驅動模式的Java程序設計》課件第七章_第4頁
《基于任務驅動模式的Java程序設計》課件第七章_第5頁
已閱讀5頁,還剩45頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第一節線程的概念線程,有時被稱為輕量級進程(LightweightProcess,LWP),是程序執行流的最小單元。一個標準的線程由線程ID、當前指令指針(PC)、寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有運行中必需的資源,但它可與同屬一個進程的其他線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以并發執行。由于線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。每一個程序至少有一個線程,若程序只有一個線程,那就是程序本身。第一節線程的概念以前古老的DOS操作系統(V6.22)是單任務的,還沒有線程的概念,系統在每次只能做一件事情。比如在復制文件的時候就不能重命文件名。為了提高系統的利用效率,采用批處理來批量執行任務。第一節線程的概念一、線程、進程和多任務現在的操作系統都是多任務操作系統,每個運行的任務就是操作系統所做的一件事情,比如在聽歌的同時還在用MSN和好友聊天。聽歌和聊天就是兩個任務,這個兩個任務是“同時”進行的。一個任務一般對應一個進程,也可能包含好幾個進程。比如運行的MSN就對應一個MSN的進程,如果用戶使用的是Windows系統,就可以在任務管理器中看到操作系統正在運行的進程信息。第一節線程的概念一般來說,當運行一個應用程序的時候,就啟動了一個進程,當然有些會啟動多個進程。啟動進程的時候,操作系統會為進程分配資源,其中最主要的資源是內存空間,因為程序是在內存中運行的。在進程中,有些程序流程塊是可以亂序執行的,并且這個流程塊可以同時被多次執行。實際上,這樣的流程塊就是線程體。線程是進程中亂序執行的代碼流程。當多個線程同時運行的時候,這樣的執行模式就成為并發執行。第一節線程的概念線程與進程的比較如下:(1)進程:每個進程都有獨立的代碼和數據空間(進程上下文),進程切換的開銷大。(2)線程:即輕量的進程,同一類線程共享代碼和數據空間。每個線程有獨立的運行棧和程序計數器(PC),線程切換的開銷小。(3)多進程:在操作系統中能同時運行多個任務程序。(4)多線程:在同一應用程序中有多個順序流同時執行。第一節線程的概念多線程機制是Java語言的又一重要特征,使用多線程技術可以使系統同時運行多個執行體,這樣可以加快程序的響應時間,提高計算機資源的利用率。使用多線程技術可以提高整個應用系統的性能。在Java中,創建線程有兩種方法:一種是通過創建Thread類的子類來實現;另一種是通過實現Runnable接口的類來實現。第一節線程的概念二、Java中的多線程第二節多線程程序設計從Thread類繼承是創建一個線程較為簡便的方法。在繼承這個類之后,我們需要覆蓋它的run方法,每一個線程都會分別執行一次run方法。第二節多線程程序設計一、從Thread類繼承下面程序是一個多線程的實例。在這個程序中有兩個線程,每個線程都會執行一次run方法,但是兩個線程執行的順序并不固定,因此,輸出誰先誰后都是隨機的。程序后面是某一次運行的輸出(注意每次運行都會不同)。注意,創建線程后,start方法用于啟動線程。第二節多線程程序設計【示例7.1】通過繼承類Thread構造線程體。classSimpleThreadextendsThread{publicSimpleThread(Stringstr){super(str);}publicvoidrun(){//重寫run方法for(inti=0;i<10;i++){//打印次數和線程的名字第二節多線程程序設計System.out.println(i+""+getName());try{//線程睡眠把控制權交出去sleep((int)(Math.random()*1000));}catch(InterruptedExceptione){

}}System.out.println("DONE!"+getName());}}第二節多線程程序設計publicclassHelloWorld{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubnewSimpleThread("第一個線程").start();newSimpleThread("第二個線程").start();}}第二節多線程程序設計運行結果:0第一個線程0第二個線程1第二個線程1第一個線程2第二個線程3第二個線程2第一個線程3第一個線程4第二個線程4第一個線程第二節多線程程序設計5第一個線程5第二個線程6第二個線程6第一個線程7第一個線程7第二個線程8第一個線程9第一個線程DONE!第一個線程8第二個線程9第二個線程DONE!第二個線程第二節多線程程序設計說明:程序啟動運行main的時候,Java虛擬機啟動一個進程,主線程main在main()調用的時候被創建。隨著SimpleThread兩個對象的start方法的調用,另外兩個線程也啟動了,這樣整個應用就在多線程下運行。第二節多線程程序設計在一個方法中調用Thread.currentThread().getName()方法,可以獲取當前線程的名字。在mian方法中調用該方法,獲取的是主線程的名字。注意:start()方法的調用后并不是立即執行多線程代碼,而是使該線程變為可運行態(Runnable),什么時候運行是由操作系統決定的。第二節多線程程序設計從程序運行的結果可以發現,多線程程序是亂序執行。因此,只有亂序執行的代碼才有必要設計為多線程。Thread.sleep()方法的調用目的是不讓當前線程獨自占有該進程所獲取的CPU資源,以留出一定時間給其他線程執行的機會。實際上所有的多線程代碼執行順序都是不確定的,每次執行的結果都是隨機的。第二節多線程程序設計【示例7.2】通過接口構造線程體。publicclassClockextendsjava.applet.AppletimplementsRunnable{ //實現接口ThreadclockThread;publicvoidstart(){//該方法是Applet的方法不是線程的方法if(clockThread==null){clockThread=newThread(this,"Clock");第二節多線程程序設計二、實現Runnable接口/*線程體是Clock對象本身線程名字為"Clock"*/clockThread.start(); //啟動線程}}

publicvoidrun(){ //run()方法中是線程執行的內容while(clockThread!=null){repaint(); //刷新顯示畫面第二節多線程程序設計try{clockThread.sleep(1000);//睡眠1秒即每隔1秒執行一次}catch(InterruptedExceptione){}}}publicvoidpaint(Graphicsg){Datenow=newDate();//獲得當前的時間對象第二節多線程程序設計g.drawString(now.getHours()+":"+now.getMinutes()+":"+now.getSeconds(),5,10);//顯示當前時間}publicvoidstop(){//該方法是Applet的方法不是線程的方法clockThread.stop();clockThread=null;}}第二節多線程程序設計以上示例是通過每隔1秒就執行線程的刷新畫面功能來顯示當前的時間;看起來的效果就是一個時鐘每隔1秒就變化一次。由于采用的是實現接口Runnable的方式,所以該類Clock還繼承了Applet,Clock就可以Applet的方式運行。第二節多線程程序設計構造線程體的兩種方法的比較如下:(1)使用Runnable接口。①可以將CPU代碼和數據分開,從而形成清晰的模型。②可以從其他類繼承。③保持程序風格的一致性。(2)直接繼承Thread類。①不能從其他類繼承。②編寫簡單,可以直接操作線程無需使用Thread.currentThread()。第二節多線程程序設計第三節多線程的狀態處理線程的狀態可分為就緒、運行、阻塞、死亡等。就緒:當線程創建之后,調用start方法,自動運行run方法。此時,線程獲得了系統資源,并處于等待CPU的狀態。運行:線程獲得了CPU資源。阻塞:處于運行狀態的線程因為缺少某種資源而不得不停止運行,進入阻塞狀態。死亡:線程的run方法運行結束時,線程進入死亡狀態。第三節多線程的狀態處理一、線程的狀態線程終止后其生命周期也就結束了,即進入死亡狀態,終止后的線程不能再被調度執行。以下是進入死亡狀態的幾種情況線程:(1)線程執行完其run()方法后會自然終止。(2)通過調用線程的實例方法stop()來終止線程。第三節多線程的狀態處理二、對線程狀態的控制1.終止線程可以通過Thread中的isAlive()方法來獲取線程是否處于活動狀態。第三節多線程的狀態處理2.測試線程狀態有幾種方法可以暫停一個線程的執行,并在適當的時候再恢復其執行。(1)?sleep()方法。當前線程睡眠(停止執行),即若干毫秒線程由運行中狀態,進入不可運行狀態,停止執行時間到后線程進入可運行狀態。(2)?suspend()和resume()方法。線程的暫停和恢復通過調用線程的suspend()方法使線程暫時由可運行態切換到不可運行態,若此線程想再回到可運行態,必須由其他線程調用resume()方法來實現。注:從JDK1.2開始就不再使用suspend()和resume()。(3)?join()方法。當前線程等待調用該方法的線程結束后,再恢復執行。第三節多線程的狀態處理3.線程的暫停和恢復第四節線程的同步與共享因為多線程提供了程序的異步執行的功能,可能會出現兩個或多個線程同時訪問共享資源,所以在必要時還必須提供一種同步機制。線程同步可以確保當兩個或多個線程需要訪問共享資源時,一次只有一個線程使用資源。第四節線程的同步與共享在Java中,使用synchronized關鍵字修飾的方法稱為同步方法。當某一線程在一個同步方法中執行的時候,其他所有企圖調用同步方法的線程或者其他方法都必須等待。第四節線程的同步與共享一、線程的同步1.線程的同步機制【示例7.3】使用synchronized。classTarget{synchronizedvoiddisplay(intnum){System.out.println("begin"+num);try{Thread.sleep(1000);}catch(Exceptione){System.out.println("Interrupted");}System.out.println("end");}}第四節線程的同步與共享在Java中使用synchronized的兩種方式如下:(1)放在方法前面,這樣調用該方法的線程均將獲得對象的鎖。(2)放在代碼塊前面,它也有以下兩種形式:synchronized(this){…}:代碼塊中的代碼將獲得當前對象引用的鎖。synchronized(otherObj){…}:代碼塊中的代碼將獲得指定對象引用的鎖。第四節線程的同步與共享線程系統還存在一個更大的風險,即“死鎖”。死鎖是保護數據不受線程損壞的自然結果。如果共享資源有狀態,而且在多個線程處于活動狀態時更改代碼塊的狀態,則當多個線程運行時,就可能會潛在地破壞資源狀態。線程是獨立調度的,不一定按固定順序運行,這必然存在風險。要解決這個問題,應將數據設置為私有,并同步代碼塊。第四節線程的同步與共享2.死鎖但是,如果在應用程序中定義同步代碼,則可能出現死鎖。具體地講,對于兩個已經有鎖標記的線程而言,如果它們都試圖調用受另一個線程的鎖標記保護的同步代碼,則可能出現死鎖。在出現死鎖時,兩個線程將永不能再運行。另外,調用使用相同鎖標記的方法的其他線程也將出現死鎖。第四節線程的同步與共享當以下四個條件同時滿足時,就會發生死鎖:(1)互斥條件。線程使用的資源中至少有一個是不能共享的。(2)至少有一個進程必須有一個資源且正在等待獲取一個當前被別的進程持有的資源。(3)資源不能被進程搶占。所有的進程必須把資源釋放當作普通事件。(4)必須有循環等待。一個進程等待其他進程所持有的資源,這時,后者又在等待另一個進程所持有的資源,這樣直到有一個進程在等待第一個進程所持有的資源,使大家都被鎖住。所以,要防止死鎖發生,只需破壞其中一個條件即可。在程序中,防止死鎖最容易的方法是破壞條件(4)。第四節線程的同步與共享線程調度器按線程的優先級高低來選擇高優先級線程(進入運行中狀態),執行同時,線程調度是搶先式調度,即如果在當前線程執行過程中一個更高優先級的線程進入可運行狀態,則這個線程立即被調度執行。線程的優先級用數字來表示范圍從1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一個線程的缺省優先級是5,即Thread.NORM_PRIORITY。第四節線程的同步與共享二、線程的優先級本節將討論如何控制互相交互的線程之間的運行進度,即多線程之間的同步問題。下面我們將通過多線程同步的模型,即生產者—消費者問題來說明怎樣實現多線程的同步。第四節線程的同步與共享三、生產者—消費者問題對于此模型,應該明確以下幾點:(1)生產者僅僅在倉儲未滿時候生產,倉滿則停止生產。(2)消費者僅僅在倉儲有產品時候才能消費,倉空則等待。(3)當消費者發現倉儲沒產品可消費時,會通知生產者生產。(4)生產者在生產出可消費產品時,應該通知等待的消費者去消費。第四節線程的同步與共享我們把系統中使用某類資源的線程稱為消費者,產生或釋放同類資源的線程稱為生產者。在下面Java的應用程序中生產者線程向文件中寫數據,消費者從文件中讀數據,這樣在這個程序中同時運行的兩個線程共享同一個文件資源。通過這個例子我們來了解怎樣使它們同步。第四節線程的同步與共享【示例7.4】生產者和消費者兩個線程共享同一個文件資源。//生產者與消費者共享的緩沖區,必須實現讀、寫的同步publicclassBuffer{privateintcontents;privatebooleanavailable=false;publicsynchronizedintget(){while(!available){第四節線程的同步與共享try{this.wait();}catch(InterruptedExceptionexc){}}intvalue=contents;//消費者取出內容,改變存取控制availableavailable=false;System.out.println("取出"+contents);this.notifyAll();returnvalue;}第四節線程的同步與共享publicsynchronizedvoidput(intvalue){while(available){try{this.wait();}catch(InterruptedExceptionexc){}}contents=value;available=true;System.out.println("放入"+contents);this.notifyAll();第四節線程的同步與共享}}//生產者線程publicclassProducerextendsThread{privateBufferbuffer;privateintnumber;publicProducer(Bufferbuffer,intnumber){this.buffer=buffer;this.number=number;}第四節線程的同步與共享publicvoidrun(){for(inti=0;;){buff

溫馨提示

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

評論

0/150

提交評論