




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Java多線程Java應用開發與實踐
酒店管理系統的設計學習目標理解進程和線程的區別和聯系掌握線程的創建方法了解線程同步的概念了解線程調度的概念10.1進程和線程10.2線程的創建10.3線程同步10.4線程調度10.5實訓10多線程的練習和應用目錄10.1進程和線程進程是一個在內存中運行的應用程序。每個進程都有獨立的代碼和數據空間(進程上下文),有它特定的進程號。他們共享系統的內存資源,進程間的切換會有較大的開銷,一個進程包含若干個線程,進程是資源分配的最小單位。線程是進程中的一個執行任務(控制單元),負責當前進程中程序的執行。一個進程至少有一個線程,一個進程可以運行多個線程,多個線程共享進程的堆和方法區資源,同時每個線程有獨立的運行棧和程序計數器(PC),線程切換開銷小,因此線程也被稱為輕量級進程。線程是CPU調度的最小單位。由于線程是操作系統直接支持的執行單元,因此,高級語言通常都內置多線程的支持,Java也不例外。10.1.1認識進程和線程10.1進程和線程1)多線程技術使程序的響應速度更快,因為用戶界面可以在進行其它工作的同時一直處于活動狀態;2)當前沒有進行處理的任務時可以將處理器時間讓給其它任務;3)占用大量處理時間的任務可以定期將處理器時間讓給其它任務;4)可以隨時停止任務;5)可以分別設置各個任務的優先級以優化系統的性能。在以下情況下,最適合采用多線程處理:1)耗時或大量占用處理器的任務阻塞用戶界面操作;2)各個任務必須等待外部資源(如遠程文件或Internet連接)。10.1.2多線程的特點10.1進程和線程在Java中任何對象都有生命周期,線程也不例外,線程的創建即是線程的生命周期的開始,當run()方法執行完畢或者線程拋出一個未捕獲的異常或者錯誤的時候,線程死亡。因此線程從創建到死亡的過程就是一個動態執行的過程。10.1.3線程的生命周期及五種基本狀態10.1進程和線程10.1.3線程的生命周期及五種基本狀態10.1進程和線程新建狀態(new):當線程對象對創建后,即進入了新建狀態,如: Threadt=newMyThread();就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處于就緒狀態的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執行,并不是說執行了t.start()此線程立即就會執行;運行狀態(Running):當CPU開始調度處于就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。就緒狀態是進入到運行狀態的唯一入口。也就是說,線程要想進入運行狀態執行,首先必須處于就緒狀態中;10.1.3線程的生命周期及五種基本狀態10.1進程和線程阻塞狀態(Blocked):處于運行狀態中的線程由于某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才有機會再次被CPU調用以進入到運行狀態。死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。10.1.3線程的生命周期及五種基本狀態10.2線程的創建Thread類是java.lang包下的一個常用類,每一個Thread類的對象,就代表一個處于某種狀態的線程。Thread類用于操作線程,是所有涉及到線程的操作(如并發)的基礎。創建線程比較常用的一種方法就是繼承Thread類。如果應用系統只需要建立一條線程,而沒有什么其它特殊的要求,那么繼承Thread類無疑是較好的選擇。Thread類中的方法可分為實例方法和靜態方法,其中實例方法有start()方法,run()方法等,靜態方法有currentThread()方法,sleep(longmillis)方法等。10.2.1通過繼承Thread類創建線程10.2線程的創建1.start()方法start()用來啟動一個線程,當調用start()方法后,系統才會開啟一個新的線程來執行用戶定義的子任務,在這個過程中,會為相應的線程分配需要的資源。要注意,調用start方法的順序不代表線程啟動的順序,也就是CPU執行哪個線程的代碼具有不確定性。10.2.1通過繼承Thread類創建線程10.2線程的創建2.run()方法這個方法是線程類調用start()后所執行的方法,如果直接調用run()而不是start()方法,那么和普通方法一樣沒有區別。要注意,run()方法是不需要用戶來調用的,當通過start()方法啟動一個線程之后,當線程獲得了CPU執行時間,便進入run()方法體去執行具體的任務。用start()方法來啟動線程,是真正實現了多線程,通過調用Thread類的start()方法來啟動一個線程,這時此線程處于就緒(可運行)狀態,并沒有運行,一旦得到CPU時間片,就開始執行run()方法,無需等待run()方法執行完畢,即可繼續執行下面的代碼。所以說:start()方法是真正實現了多線程,run()方法只是一個普通的方法。10.2.1通過繼承Thread類創建線程10.2線程的創建3.interrupt()方法使用這個方法不會中斷線程。實際上調用interrupt實際作用是在線程受到阻塞時拋出一個中斷信號,這樣線程就得以退出阻塞狀態。4.join()方法join方法會使得調用join方法的線程無限阻塞,直到調用join方法的線程銷毀為止,join方法內部使用的是wait(),所以會釋放鎖。10.2.1通過繼承Thread類創建線程10.2線程的創建5.sleep(longmillis)方法sleep()方法是靜態方法,它的作用就是在指定的時間(單位是毫秒)讓正在執行的線程休眠,不釋放鎖。后面小節有詳述。6.yield()方法暫停當前執行的線程對象,并執行其他線程。這個暫停會放棄CPU資源,放棄的時間不確定。10.2.1通過繼承Thread類創建線程10.2線程的創建繼承Thread類的步驟如下:1)定義類繼承Thread類;2)重寫Thread類中的run()方法;重寫run()方法的目的是將需要該線程執行的代碼存儲在run()方法運行。3)調用線程的start方法。該方法有兩步:啟動線程,調用run()方法。10.2.1通過繼承Thread類創建線程10.2線程的創建classMyThreadextendsThread{ publicvoidrun(){ for(inti=0;i<10;i++){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ e.printStackTrace(); }//this.getName()獲取當前線程
System.out.println(this.getName()); } }}10.2.1通過繼承Thread類創建線程10.2線程的創建publicclassDemo10_1{ publicstaticvoidmain(String[]args){ MyThreadthead1=newMyThread(); MyThreadthead2=newMyThread(); thead1.start(); thead2.start(); }}10.2.1通過繼承Thread類創建線程10.2線程的創建實現Runnable接口的步驟如下:1)定義類實現Runnable接口;2)實現Runnable接口中的run()方法,將線程要運行的代碼放在該run()方法中;3)通過Thread類建立線程對象;4)將Runnable接口的子類對象作為實際參數傳遞給Thread類的構造函數。自定義的run()方法所屬的對象是Runnable接口的子類對象。5)調用Thread類的start()方法開啟線程并調用Runnable接口子類的run()方法。10.2.2通過實現Runnable接口創建線程10.2線程的創建classMyThreadimplementsRunnable{ publicvoidrun(){ for(inti=0;i<10;i++){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } //Thread.currentThread()獲取當前線程 System.out.println(Thread.currentThread().getName()); } }}10.2.2通過實現Runnable接口創建線程10.2線程的創建publicclassDemo10_2{ publicstaticvoidmain(String[]args){ MyThreadthread1=newMyThread(); MyThreadthread2=newMyThread(); Threadth1=newThread(thread1,"MyThread1"); Threadth2=newThread(thread2,"MyThread2"); th1.start(); th2.start(); }}10.2.2通過實現Runnable接口創建線程10.2線程的創建繼承Thread類和實現Runnable接口都可以創建線程。在繼承Thread的方式中,線程代碼是存放在Thread子類run()方法中,線程對象和線程任務耦合在一起。一旦創建Thread類的子類對象,既是線程對象,有又有線程任務。優點是編寫簡單,可直接用this.getname()獲取當前線程,不必使用Thread.currentThread()方法。但缺點也有,就是已經繼承了Thread類后,無法再繼承其他類。實現Runnable接口的方式較為常用,實現Runnable接口的方式,更加的符合面向對象的思想:線程分為兩部分,一部分線程對象,一部分線程任務。將線程任務單獨分離出來封裝成對象,存放在接口的子類的run()方法中,類型就是Runnable接口類型。此方式優點是避免了單繼承的局限性、多個線程可以共享一個target對象,非常適合多線程處理同一份資源的情形。缺點是比較復雜、訪問線程必須使用Thread.currentThread()方法、無返回值。10.2.3繼承Thread類和實現Runnable接口的區別10.3線程同步線程同步就是指各個線程協同步調,按預定的先后次序進行運行。這里的“同”字意思就是指協同、協助、互相配合。多線程通過特定的設置(如互斥量,事件對象,臨界區)來控制線程之間的執行順序(即所謂的同步)也可以說是在線程之間通過同步建立起執行順序的關系,如果沒有同步,那線程之間是各自運行各自的。線程同步的主要任務是使并發執行的各線程之間能夠有效的共享資源和相互合作,從而使程序的執行具有可再現性。通常,在多線程編程里面,一些敏感數據不允許被多個線程同時訪問,此時就使用同步訪問技術,保證數據在任何時刻,最多有一個線程訪問,以保證數據的完整性。10.3.1線程同步10.3線程同步線程互斥是指對于共享的進程系統資源,在各單個線程訪問時的排它性。當有若干個線程都要使用某一共享資源時,任何時刻最多只允許一個線程去使用,其它要使用該資源的線程必須等待,直到占用資源者釋放該資源。線程互斥可以看成是一種特殊的線程同步。所以,可以看出,在多個線程之間都需要訪問共享資源(sharedresource)的時候就會出現互斥現象。10.3.2線程互斥10.3線程同步線程同步的機制有臨界區、互斥量、事件、信號量四種方式。1.臨界區:在一段時間內只允許一個線程訪問的資源就稱為臨界資源或獨占資源,計算機中大多數物理設備,進程中的共享變量等待都是臨界資源,它們要求被互斥的訪問。每個進程中訪問臨界資源的代碼稱為臨界區。在任意時刻只允許一個線程對共享資源進行訪問,如果有多個線程試圖訪問公共資源,那么在有一個線程進入后,其他試圖訪問公共資源的線程將被掛起,并一直等到進入臨界區的線程離開,臨界區在被釋放后,其他線程才可以搶占。10.3.3線程同步機制10.3線程同步線程同步的機制有臨界區、互斥量、事件、信號量四種方式。2、互斥量:互斥量和臨界區很像,采用互斥對象機制,只有擁有互斥對象的線程才有訪問公共資源的權限。因為互斥對象只有一個,所以能保證公共資源不會同時被多個線程同時訪問。當前擁有互斥對象的線程處理完任務后必須將線程交出,以便其他線程訪問該資源。10.3.3線程同步機制10.3線程同步線程同步的機制有臨界區、互斥量、事件、信號量四種方式。3.信號量:信號量是維護0到指定最大值之間的同步對象。信號量狀態在其計數大于0時是有信號的,而其計數是0時是無信號的。信號量對象在控制上可以支持有限數量共享資源的訪問。4.事件:通過通知操作的方式來保持線程的同步,還可以方便實現對多個線程的優先級比較的操作。10.3.3線程同步機制10.4線程調度線程可以劃分優先級,線程的優先級告訴CPU該線程的重要程度有多大。每個線程都具有優先級,Java虛擬機根據線程的優先級決定線程的執行順序。程序會盡可能地先運行優先級高的那個程序,這樣使多線程合理共享CPU資源而不會產生沖突。通常優先級高的線程得到的CPU資源較多,也是CPU優先執行優先級較高的線程對象中的任務。程序盡可能運行優先級高的程序,并不意味著優先級較低的線程絕對不會運行。若程序的優先級較低,只不過表示它被允許的運行的幾率小一些而已。Java中的線程優先級分為1(Thread.MIN_PRIORITY)-10(Thread.MAX_PRIORITY),數字越大,優先級越高10.4.1線程優先級的設置10.4線程調度線程休眠通常是調用Thread.sleep(毫秒數)方法,讓當前運行的線程進入TIMED_WAITING(sleeping)阻塞狀態,該方法使當前線程進入休眠狀態,直到休眠設置的毫秒數后由系統喚醒,sleep方法上有一個異常。如果打斷休眠就會拋出這個異常。publicstaticvoidsleep(longmills)throwsInterruptedException10.4.2線程休眠10.4線程調度Java允許多線程并發控制,當多個線程同時操作一個可共享資源變量時(如對其進行增刪改查操作),會導致數據不準確,而且相互之間產生沖突。加入同步鎖以避免該線程在沒有完成操作前被其他線程調用,從而保證該變量的唯一性和準確性。在程序中需要完成下面兩個操作:1)把競爭訪問的資源標識為private;2)同步那些修改變量的代碼,使用synchronized關鍵字同步方法或代碼。10.4.3線程同步10.4線程調度從本質上說,synchronized是一種鎖機制,它是為一個對象或者一個類標明一個鎖,當線程想要執行相應的synchronized修飾的代碼塊時,它需要獲得synchronized修飾的對象或者類的鎖,這個就是CPU的使用權。只有拿到了鎖才可以被CPU調度,獲得處理權。當synchronized代碼塊執行結束后,這個線程就要釋放相應的鎖。CPU可以把這個鎖分給其它的線程。synchronized可以作為函數的修飾符,也可作為函數內的語句,即同步函數或同步代碼塊來實現線程同步,因此它們都是同步鎖。10.4.3線程同步10.4線程調度1.join()方法在很多情況下,主線程生成并起動了子線程,如果子線程里要進行大量的耗時的運算,主線程往往將于子線程之前結束,但是如果主線程處理完其他的事務后,需要用到子線程的處理結果,也就是主線程需要等待子線程執行完成之后再結束,這個時候就要用到join()方法了。join()方法主要作用是掛起(即插隊)。10.4.4線程常用方法10.4線程調度2.yield()方法yield()方法可以對當前線程進行臨時暫停(讓線程將資源釋放出來),供所有線程競爭。3.wait()方法和notify()方法wait()方法類似sleep(),不同的是,wait()會先釋放鎖住的對象,然后再執行等待的動作。注意,這個函數屬于Object類。另外,由于wait()所等待的對象必須先鎖住,因此,它只能用在同步化程序段或者同步化方法內,否則,會拋出異常IllegalMonitorStateException。10.4.4線程常用方法10.4線程調度兩個或者多個線程同時想要去獲取共享資源的鎖,但每個線程都要等其他線程把他們各自的鎖給釋
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年信息系統管理師備考試題集合
- 評估2025年公共政策的風險管理試題及答案
- 滑板公園企業制定與實施新質生產力項目商業計劃書
- 電子音樂派對場地行業深度調研及發展項目商業計劃書
- 歷史文化街區企業制定與實施新質生產力項目商業計劃書
- 棒球AI應用行業深度調研及發展項目商業計劃書
- 濕地博物館企業制定與實施新質生產力項目商業計劃書
- 歷史文化建筑復原企業制定與實施新質生產力項目商業計劃書
- 田徑全能訓練行業跨境出海項目商業計劃書
- 創意零售集合店行業跨境出海項目商業計劃書
- 2025年慶六一兒童節校長致辭(2篇)
- 房屋市政工程生產安全重大事故隱患排查表(2024版)
- 人教版小學數學五年級下冊全冊導學案
- 油庫設備維護規范
- 國企求職指南培訓
- 職業道德與法治綜合練習2024-2025學年中職高教版
- 【MOOC】《學術寫作與國際發表》(北京科技大學)章節測驗慕課答案
- 房屋市政工程生產安全重大事故隱患判定標準(2024版)宣傳畫冊
- 安委會辦公室主要職責
- 項目合作分潤合同范例
- 《員工質量意識培訓》課件
評論
0/150
提交評論