




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第2章多線程(一)Java高級程序設(shè)計回顧Java中的File類提供了大量的方法對文件或目錄進行操作。使用FilenameFilter接口可以輔助實現(xiàn)文件過濾功能。IO流主要用于讀寫文件,按功能可以分為輸入流、輸出流,按內(nèi)容格式可以分為字節(jié)流、字符流。字節(jié)流可以讀寫任何文件,包括文本文件、音視頻等,字符流只能讀寫文本文件。FileInputStream和FileOutputStrem是基于字節(jié)流的輸入、輸出流操作類。Reader和Writer是基于字符的輸入、輸出流操作類。本章內(nèi)容線程的概念使用Runnable接口使用線程掌握控制線程握線程的生命周期使用線程模擬人員跑步使用Runnable接口模擬人員購票使用線程拷貝文件,顯示拷貝過程使用線程模擬清掃路面2.1線程的概述進程和線程多線程的優(yōu)勢Thread類使用線程模擬人員跑步25202.1線程的概述
程序的運行默認僅包含一個主線程,所有的工作都由主線程承擔(dān),當(dāng)任務(wù)繁重耗時,會對于主線程產(chǎn)生很大壓力,甚至引起阻塞卡頓。
將繁重耗時的任務(wù)分出一些子線程去執(zhí)行,相當(dāng)于多人做一件事,能大大降低主線程的阻塞,同時提高程序運行效率。2.1.1進程幾乎所有的操作系統(tǒng)都只是同時運行多個任務(wù),一個任務(wù)通常只對應(yīng)一個程序,每個運行的程序就是一個進程。當(dāng)一個程序進入到內(nèi)存中運行時,即變?yōu)橐粋€進程。進程是處于運行過程中的程序,并且具有一定的獨立功能,進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位。
進程具有以下特點:獨立性動態(tài)性并發(fā)性2.1.1線程線程是進程的組成部分,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程之間是獨立運行,線程的執(zhí)行是搶占式的,即當(dāng)前任何運行的線程在任何時候都有可能被停止,被其他線程搶走對CPU的使用權(quán)。每個小兵、英雄都是一個獨立線程整個游戲就是一個進程2.1.2多線程優(yōu)勢多線程來實現(xiàn)并發(fā)比使用多進程實現(xiàn)并發(fā)的性能要高,在執(zhí)行耗時任務(wù)時,開啟多個線程能提高執(zhí)行效率。使用多線程編程具有以下優(yōu)點:進程之間不共享內(nèi)存,但線程之間共享內(nèi)存非常容易創(chuàng)建線程代價較小,能提高任務(wù)執(zhí)行效率Java內(nèi)置了多線程功能支持,大大簡化了多線程編程實現(xiàn)2.1.3Thread類Java使用java.lang.Thread類表示線程,所有的線程對象都必須是Thread類或其子類的實例。通過繼承Thread類來創(chuàng)建并啟動多線程的步驟如下:定義類繼承Thread類,并重寫該類的run()方法(run方法是線程的執(zhí)行主體方法)創(chuàng)建Thread子類的實例,即創(chuàng)建線程對象調(diào)用線程對象的start()方法,啟動該線程2.1.3Thread類常用方法方法名作用voidsetName(Stringname)設(shè)置線程的名字StringgetName()返回當(dāng)前線程的名字ThreadcurrentThread()返回當(dāng)前正在執(zhí)行的線程對象voidstart()啟動線程StringgetAbsolutePath()返回此File對象所對應(yīng)的絕對路徑名voidrun()線程一旦執(zhí)行,便調(diào)用此方法booleanisLive()判斷當(dāng)前線程是否活躍,活躍返回true,否則,返回false2.1.3Thread類實現(xiàn)多線程實現(xiàn)步驟1:創(chuàng)建類繼承Thread類,并且重寫run方法。run方法中完成線程執(zhí)行任務(wù)的代碼。publicclassThreadSimpleextendsThread{ privateinti=0; //重寫run()方法 publicvoidrun(){ for(;i<50;i++){ //getName()用于獲取當(dāng)前線程的名字 System.out.println(this.getName()+"\t"+i); }}2.1.3Thread類實現(xiàn)多線程實現(xiàn)步:2:在測試類的main方法中,創(chuàng)建線程子類實例對象,調(diào)用start方法啟動線程。publicstaticvoidmain(String[]args){ //創(chuàng)建并啟動第一個線程 newThreadSimple().start(); //創(chuàng)建并啟動第二個線程 newThreadSimple().start(); for(intj=0;j<20;j++){ //調(diào)用Thread的靜態(tài)方法currentThread() //獲取當(dāng)前線程運行實例 ThreadcurrentThread=Thread.currentThread(); System.out.println(currentThread.getName()+"\t"+j); }}2.1.3Thread類實現(xiàn)多線程進行多線程編程時,Java程序運行時默認的主線程即為main()方法體,該方法就是主要線程的線程執(zhí)行體。使用繼承Thread類的方式創(chuàng)建線程類時,多個線程之間無法共享線程類的實例變量(案例線程類中聲明的變量i無法被多個線程共享使用)。2.1.4學(xué)生實踐練習(xí)跑道長50m,模擬3名學(xué)生同時在跑道跑步的場景。3名同學(xué)相當(dāng)于3個線程對象。202.1.4學(xué)生實踐練習(xí)(1)創(chuàng)建Java項目,在項目中創(chuàng)建StudentRunning類,該類繼承Thread類。(2)重寫StudentRunning類的run()方法,實現(xiàn)模擬變量自增。(3)在類中定義String類型的變量name,用來保存學(xué)生的姓名。(4)在類中定義有參構(gòu)造方法,目的通過構(gòu)造方法給實例變量name賦值。(5)在StudentRunning類的main()方法內(nèi),使用有參構(gòu)造方法創(chuàng)建3個線程對象,實參name的值即3名學(xué)生的姓名。
(6)依次調(diào)用3條線程的start()方法,啟動線程。2.2Runnable接口Runnable接口介紹Runnable接口實現(xiàn)使用線程模擬人員跑步25202.2.1Runnable接口通過繼承Thread類雖然可以實現(xiàn)多線程,但是無法實現(xiàn)多線程之間的資源共享,通過Runnable接口實現(xiàn)多線程可以很好解決這個問題。Runnable接口的使用步驟如下:定義Runnable接口的實現(xiàn)類,并重寫該接口的run()方法為線程執(zhí)行主體創(chuàng)建Runnable實現(xiàn)類的實例,并以該實例作為Thread實例操作的目標創(chuàng)建Thread類對象時傳入實現(xiàn)Runnable接口的類對象Runnable對象僅作為Thread類對象操作的目標對象,而實際的線程對象依然是Thread類的實例2.2.2使用Runnable接口實現(xiàn)多線程實現(xiàn)步驟1:創(chuàng)建類實現(xiàn)Runnable接口,并且重寫run方法。run方法中完成線程執(zhí)行任務(wù)的代碼。publicclassRunnableSimpleimplementsRunnable{ privateinti=1; //重寫run()方法,run()方法同樣是線程執(zhí)行體 publicvoidrun(){ for(;i<=20;i++){ //當(dāng)實現(xiàn)Runnable接口時,獲取當(dāng)前線程,只能使用Thread.currentThread()方法 System.out.println(Thread.currentThread().getName()+"\t"+i); } }}2.2.2使用Runnable接口實現(xiàn)多線程實現(xiàn)步驟2:在測試類的main方法中,創(chuàng)建Runnable子類實例對象,作為線程對象執(zhí)行的目標。創(chuàng)建Thread類實例,傳入Runnable子類對象(這里可以多個線程使用同一個目標)。調(diào)用start()方法啟動線程。//創(chuàng)建RunnableSimple實例RunnableSimplers=newRunnableSimple();//創(chuàng)建Thread線程實例,該線程操作rs對象Threadthread=newThread(rs);thread.setName(“線程A”);//設(shè)置第一個線程的名字//創(chuàng)建第2個Thread線程實例Threadthread_02=newThread(rs);thread_02.setName("線程B");//啟動線程Athread.start();//啟動線程Bthread_02.start();2.2.2Thread和RunnableThread類和Runnable接口都可以實現(xiàn)多線程,但是Thread方式的子類直接就是線程類,實例化后直接啟動;而Runnable方式創(chuàng)建的類僅為線程的執(zhí)行提供目標,最終還是依靠Thread類創(chuàng)建線程對象。Runnable方式具有以下優(yōu)勢:適合多個相同程序代碼的線程去處理同一個資源。避免Java特性中的單根繼承限制、更能體現(xiàn)面向?qū)ο筇攸c。增加程序健壯性。在數(shù)據(jù)被共享時,仍然可以保持代碼和數(shù)據(jù)的分離。在實現(xiàn)多線程時,更推薦大家使用Runnable接口2.2.3學(xué)生實踐練習(xí)車站只剩50張從武漢到北京的車票,現(xiàn)有3個窗口售賣,用程序模擬售票的過程。202.2.3學(xué)生實踐練習(xí)(1)創(chuàng)建SellTicket類實現(xiàn)Runnable接口,定義實例變量ticket賦值50,重寫run方法。(2)在run方法內(nèi),定義while死循環(huán)。在循環(huán)體中,調(diào)用Thread類的靜態(tài)方法Thread.currentThread().getName()獲取當(dāng)前運行線程的名稱,打印線程名稱和 ticket變量值,然后讓ticket自減。當(dāng)ticket小于等于0時,結(jié)束循環(huán)。(4)在測試類的main()方法內(nèi),創(chuàng)建SellTicket類實例一個。(4)使用newThread(Runnabletarget)構(gòu)造方法開辟3條線程,并將Runnable實例sellTicket傳給形參target。(5)依次調(diào)用3個Thread類對象的start()方法,啟動線程。2.3控制線程Sleep線程休眠Join線程使用線程拷貝文件,顯示拷貝過程25202.3控制線程
線程的執(zhí)行過程中能否對其進行控制呢?
Java針對線程提供了一些便捷的工具方法,通過這些便捷的工具方法可以很好地控制線程的執(zhí)行。2.3.1線程休眠Thread類的sleep(longmillis)方法可以讓當(dāng)前正在執(zhí)行的線程暫停多少毫秒,并進入阻塞狀態(tài)。調(diào)用sleep()方法進入阻塞狀態(tài)后,在其睡眠時間段內(nèi),該線程不會獲得執(zhí)行的機會。2.3.1線程休眠使用sleep()方法休眠線程,實現(xiàn)每隔500毫秒出現(xiàn)一顆五角星publicvoidrun(){ //循環(huán)20次,打印出20顆五角星 for(inti=0;i<20;i++){ try{ //線程休眠500毫秒 Thread.sleep(500); System.out.print("☆"); }catch(InterruptedExceptione){ e.printStackTrace(); }}線程休眠會產(chǎn)生異常,必須處理2.3.2join線程Thread類的join()方法可以讓一條線程等待另一條線程完成。如:在線程B中,調(diào)用了線程A的join()方法后線程B則會被掛起,并進入阻塞狀態(tài),直到線程A執(zhí)行完畢后才會繼續(xù)執(zhí)行線程B。2.3.2join線程實現(xiàn)兩個線程之間等待效果:實現(xiàn)步驟創(chuàng)建線程類A繼承Thread類,重寫run方法創(chuàng)建線程類B繼承Thread類,B類中需要聲明線程A類的對象引用,以便在B類中可以使用線程A類對象線程B類run方法中,調(diào)用線程A對象的join()方法,此時線程B會處于等待狀態(tài),直到線程A執(zhí)行完畢創(chuàng)建測試類,創(chuàng)建線程A和B,分別線程A、B并運行2.3.3學(xué)生實踐練習(xí)使用Java的I/O流將H:\eclipse.zip文件拷貝至E盤下,重新命名為eclipse安裝.zip。在拷貝過程中,每隔2000毫秒顯示一次文件已經(jīng)被拷貝的大小及剩余的大小,直至文件完成拷貝,提示用戶文件已經(jīng)拷貝完成。202.3.3學(xué)生實踐練習(xí)(1)創(chuàng)建InstantThread類,該類需要繼承Thread類。(2)在InstantThread類中創(chuàng)建兩個File類型的靜態(tài)實例readFile(被拷貝的文件)和writeFile(拷貝后的文件)。(3)在InstantThread類中定義voidcopy(FilereadFile,FilewriteFile)方法,完成文件的拷貝操作,參數(shù)readFile表示要讀取的文件,參數(shù)writeFile表示重新寫入的新文件。(4)重寫InstantThread類的run()方法,該方法用于顯示文件拷貝的進度。(5)在run()方法中調(diào)用readFile的length()方法以獲取源文件的大小,并保存到long類型的變量length內(nèi)。(6)當(dāng)變量currentLength的值大于等于length變量值時,結(jié)束循環(huán)2.4線程的生命周期新建和就緒狀態(tài)運行和阻塞狀態(tài)使用線程模擬清掃路面30152.4線程的生命周期當(dāng)線程被創(chuàng)建啟動后,該線程并非一啟動就會被執(zhí)行,也不會一直處于執(zhí)行狀態(tài)。在線程的生命周期中,要經(jīng)過新建就緒運行阻塞死亡這5種狀態(tài)。多線程并非同時執(zhí)行,而是CPU在多個線程之間來回快速切換執(zhí)行,而線程本身也在運行和阻塞狀態(tài)之間切換2.4.1新建和就緒狀態(tài)當(dāng)程序使用new關(guān)鍵字創(chuàng)建線程后,該線程就處于新建狀態(tài)。當(dāng)線程對象調(diào)用了start()方法后,該線程就處于就緒狀態(tài),處于就緒狀態(tài)的線程并未開始運行,僅表示該線程可以運行,該線程何時開始運行,取決于JVM
中線程調(diào)度器的調(diào)度。啟動線程使用start()方法,而不是run()方法。永遠不要調(diào)用線程對象的run()方法2.4.2線程運行狀態(tài)如果處于就緒狀態(tài)的線程獲得了CPU,開始執(zhí)行run()方法的線程執(zhí)行體,則該線程處于運行狀態(tài)。對于單CPU的機器,任何時刻只有一個線程處于運行狀態(tài),它會在多個線程之間來回切換執(zhí)行。對于多CPU的機器,將會有與CPU個數(shù)相同的線程并行執(zhí)行。2.4.2線程阻塞狀態(tài)當(dāng)發(fā)生如下情況時,線程將進入阻塞狀態(tài):線程調(diào)用sleep()方法主動放棄占有的CPU資源線程調(diào)用了一個阻塞式的I/O方法,在方法之間,該線程被阻塞當(dāng)發(fā)生如下特定的情況時,可以解除上述阻塞,讓該線程重新進入就緒狀態(tài):調(diào)用sleep()方法的線程經(jīng)過了指定的時間線程調(diào)用的阻塞式I/O方法已經(jīng)返回2.4.2線程死亡狀態(tài)線程會以如下方式結(jié)束,結(jié)束后就處于死亡狀態(tài):run()方法執(zhí)行完成,線程正常結(jié)束線程拋出一個未捕獲的Exception或Error直接調(diào)用線程的stop()方法來結(jié)束該線程,通常不推薦使用該方法不要試圖對一個已經(jīng)死亡的線程調(diào)用其start()方法使其重新啟動,否則會拋出異常。2.4.2線程執(zhí)行狀態(tài)圖2.4.3學(xué)生實踐練習(xí)前方有3km的道路障礙,4輛普
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 45292-2025輪胎翻新生產(chǎn)技術(shù)條件
- 農(nóng)村山地承包合同管理規(guī)定其四
- 市場調(diào)研服務(wù)合同協(xié)議范本
- 詳解:中保人壽保險合同之66鴻運保險(B型)
- 超市人力資源服務(wù)合同樣本
- 計算機銷售與技術(shù)服務(wù)合同協(xié)議
- 公司機密信息保護合同
- 股東權(quán)益分紅合同范本詳解
- 100以內(nèi)的加法和減法(二)(教學(xué)設(shè)計)-2024-2025學(xué)年二年級上冊數(shù)學(xué)人教版
- 雙方合作經(jīng)營合同模板
- 網(wǎng)運分離參照德國繼續(xù)推薦京滬高鐵
- 《豐收之歌》精選教學(xué)課件
- 【青島版《科學(xué)》】四年級下冊第一單元1 《運動與力》 教學(xué)設(shè)計
- 水利工程水庫混凝土防滲墻施工方案
- 2022春蘇教版五年級下冊科學(xué)全冊單元課件全套
- 小學(xué)期末班級頒獎典禮動態(tài)PPT模板
- 液堿生產(chǎn)工序及生產(chǎn)流程敘述
- 圖解調(diào)音臺使用說明(共14頁)
- 人民軍隊性質(zhì)宗旨和優(yōu)良傳統(tǒng)教育課件教案
- 心理抗壓能力測試例題
- 操作系統(tǒng)試題
評論
0/150
提交評論