版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第十章Java線程什么是進程、線程創(chuàng)立線程的兩種方法線程的生命周期線程的類型分析1.什么是進程、線程進程:當前正在執(zhí)行的程序,稱為進程(progress) 例如:在進行網上購物時,可以邊聽音樂、收發(fā)Mail、QQ聊天等多個程序在運行??赏ㄟ^windows任務管理器查看。 每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。比方在Windows系統(tǒng)中,一個運行的exe就是一個進程。
說明:對于單CPU無法同時運行多個進程,只能交替輪流執(zhí)行多個程序。在某一時刻,CPU執(zhí)行的進程其實只有一個。1.1進程與線程在windows中可以通過任務管理器查看進程說明:CPU是一種非常珍貴的資源,它直接影響程序的運行情況。線程線程是進程中程序代碼的一個執(zhí)行序列,是一種比進程更小的執(zhí)行單位,一個進程可以包含多個線程;線程也是一個動態(tài)的概念,包含產生、存在和消亡的過程;每個進程都有一段專用的內存區(qū)域,而線程間可以共享相同的內存單元(包括代碼與數(shù)據(jù)),數(shù)據(jù)交換、實時通信、同步操作更方便。因此,線程得到廣泛應用,例如:QQ等支持多線程是Java的重要特色,它提供了Thread類來實現(xiàn)多線程;Java中的線程可以認為是由三局部組成的:虛擬CPU:封裝在類中,控制著整個線程的運行;執(zhí)行的代碼:傳遞給Thread類,由Thread類控制順序執(zhí)行;處理的數(shù)據(jù):傳遞給Thread類,是在代碼執(zhí)行過程中所要處理的數(shù)據(jù)。1.2Java中的線程代碼數(shù)據(jù)虛擬CPU以前的程序:一個入口,語句序列,一個出口。程序依次執(zhí)行,這稱為單線程。1.3多線程publicclassSequentialExample{//例1程序片段 publicstaticvoidmain(Stringargs[]){
newSequential("A").run(); newSequential("B").run(); }}classSequential{
Stringname=null; publicSequential(Stringn){//構造器 name=n; }
publicvoidrun(){ for(inti=0;i<3;i++){ try{
Thread.sleep(500);//休眠0.5秒
System.out.println("訪問:"+name);
} }}程序運行結果訪問:A訪問:A訪問:A訪問:B訪問:B訪問:B多線程:CPU交替執(zhí)行程序序列。//例2程序片段publicclassMultiThreadExample{ publicstaticvoidmain(Stringargs[]){ newMyThread("A").start(); newMyThread("B").start(); }}classMyThreadextendsThread{ publicMyThread(Stringn){//構造器 super(n); }
publicvoidrun(){ for(inti=0;i<3;i++){ try{
Thread.sleep(500);//休眠0.5秒
System.out.println("訪問:"+getName());
}catch(InterruptedExceptione){} }}程序運行可能結果訪問:A訪問:B訪問:A訪問:B訪問:A訪問:B2.創(chuàng)立線程的兩種方法從前面的例2可以知道:創(chuàng)立線程,最重要的是實現(xiàn)其中的run(),run()決定了線程所做的工作,又稱為線程體。當線程開始時,代碼publicvoidrun()被執(zhí)行可用以下兩種方法來創(chuàng)立線程類:繼承線程類Thread實現(xiàn)Runnable接口Thread類和Runnable接口都在java.lang包中,是默認導入的,不必使用import語句。可通過繼承Thread類,并重寫其中的run()方法來定義線程體,以實現(xiàn)線程的具體行為,然后創(chuàng)立該子類的對象,并啟動線程。其步驟為:(1)擴展類:2.1繼承線程類Threadpublicclass線程類名extendsThread{ ……
publicvoidrun(){ ……//編寫線程的代碼 }}(2)創(chuàng)立線程類對象(3)啟動線程:線程類對象.start();注意:不要在程序中直接調用線程的run()方法;啟動線程并不意味著線程可以立即得到執(zhí)行,這取決于線程資源的獲取情況和CPU的占有情況。Thread類的構造方法:publicThread();publicThread(Runnabletarget);publicThread(Runnabletarget,Stringname);publicThread(Stringname);publicThread(ThreadGroupgroup,Stringname);…Threadt1=newThread(pp1);其中:target表示run()所在類,name是線程(組)名Thread類的常用方法:voidrun():線程所執(zhí)行的代碼voidstart():啟動線程voidsleep(longmilis):讓線程睡眠一段時間,此期間線程不消耗CPU資源voidinterrupt():中斷線程booleanisAlive():判斷線程是否處于活動狀態(tài)(即已調用start)staticThreadcurrentThread():返回當前線程對象的引用voidsetName(StringthreadName):改變線程的名字StringgetName():獲得線程的名字Thread類的常用方法(續(xù)):voidjoin([long
millis[,int
nanos]]):等待線程結束staticvoidyield():暫停當前線程,讓其他線程執(zhí)行voidsetDaemon(booleanon):設置為守護線程voidsetPriority(intp):設置線程的優(yōu)先級notify()/notifyAll()/wait():從Object繼承而來,用于線程間通信 以下幾個方法出于平安問題考慮,現(xiàn)已不推薦使用:voiddestroy():銷毀線程voidstop():終止線程的執(zhí)行voidsuspend()/voidresume():掛起/恢復線程//例3用繼承Thread類方法創(chuàng)立線程publicclassPingPong1extendsThread{ privateintdelay; privateStringmessage; publicPingPong1(Stringm,intr){ message=m; delay=r; } publicvoidrun(){ try{ for(;;){ System.out.println(message); sleep(delay);//休眠 } }catch(InterruptedExceptione){ return; } } publicstaticvoidmain(String[]args){ PingPong1t1=newPingPong1("ping",500); PingPong1t2=newPingPong1("pong",1000); t1.start(); t2.start(); }}程序運行結果(每次可能不同)pingpongpingpongpingpingpongpingPing…任何類都可以實現(xiàn)Runnable接口,而這個類的實例將用一個線程來調用,啟動該類的run()方法。Runnable接口只有一個run()方法,其作用和Thread類的run()方法相同。創(chuàng)立步驟為:(1)定義目標類:2.2實現(xiàn)Runnable接口publicclasspingpong2
implementsRunnable{ ……
publicvoidrun(){ ……//編寫線程的代碼 }}(2)不能直接創(chuàng)立目標類對象并運行它,而是應該以目標類為參數(shù)創(chuàng)立Thread類的對象,例如:PingPong2pp1=newPingPong2(“ping”,500));Threadt1=newThread(pp1);(3)啟動線程:以目標類為參數(shù)創(chuàng)立Thread類的對象.start(); 例如:t1.start();例4與例3的功能類似,只是使用了接口方法//例4利用接口Runnalbe方法創(chuàng)立線程publicclassPingPong2implementsRunnable{ privateintdelay; privateStringmessage; publicPingPong2(Stringm,intr){ message=m; delay=r; }//例4利用接口Runnalbe方法創(chuàng)立線程 publicvoidrun(){ try{ for(;;){ System.out.println(message); Thread.sleep(delay);//休眠 } }catch(InterruptedExceptione){ return; } } publicstaticvoidmain(String[]args){ PingPong2pp1=newPingPong2("ping",500); PingPong2pp2=newPingPong2("pong",1000); Threadt1=newThread(pp1); Threadt2=newThread(pp2); t1.start(); t2.start(); }}程序運行結果(每次可能不同)pingpongpingpongpingpingpongpingpingpongping…練習線程的創(chuàng)立分別用兩種方法創(chuàng)立線程:〔1〕繼承Thread類,要求線程體輸出“由繼承Thread類創(chuàng)立線程?!薄?〕實現(xiàn)Runnable接口,要求線程體輸出“由實現(xiàn)Runnable接口創(chuàng)立線程?!庇衫^承Thread類創(chuàng)立線程的方法簡單方便,可以直接操作線程,無需使用Thread.currentThread()。但不能再繼承其他類;使用Runnable接口方法可以將CPU,代碼和數(shù)據(jù)分開,形成清晰的模型;還可以從其他類繼承;保持程序風格的一致性。2.3兩種方法的比較3.線程棧模型與線程的變量要理解線程調度的原理,以及線程執(zhí)行過程,必須理解線程棧模型。線程棧是指某時刻時內存中線程調度的棧信息,當前調用的方法總是位于棧頂。
3.線程棧模型與線程的變量當程序執(zhí)行到t.start()時,程序多出一個分支〔增加了一個調用棧B〕,這樣,棧A、棧B并行執(zhí)行。例5Join的應用classMyRunnableimplementsRunnable{ Stringname; MyRunnable(Stringstr){ name=str; } publicvoidrun(){//Runnable接口中方法 for(inti=0;i<=10;i++) System.out.println(name+""+i); } publicstaticvoidmain(String[]args)throwsInterruptedException{ MyRunnablemyr=newMyRunnable("myThread"); Threadt=newThread(myr);//創(chuàng)立線程 t.start();//啟動 t.join(); System.out.println("run()方法執(zhí)行完后線程狀態(tài):"+t.isAlive()); }}舉例:創(chuàng)立線程,求兩個數(shù)之間所有整數(shù)之和classSumThreadextendsThread{ intvar1,var2; longsum; SumThread(inti1,inti2){ var1=i1; var2=i2; } longgetSum(){ returnsum; } publicvoidrun(){//run()方法
for(inti=var1;i<=var2;i++) sum+=i; }}publicclassThread3{ publicstaticvoidmain(String[]args)throwsException{ SumThreadst=newSumThread(1,1000); st.start(); System.out.println(st.getSum());
}}結果:0classSumThreadextendsThread{ intvar1,var2; longsum; SumThread(inti1,inti2){ var1=i1; var2=i2; } longgetSum(){ returnsum; } publicvoidrun(){//run()方法
for(inti=var1;i<=var2;i++) sum+=i; }}publicclassThread3{ publicstaticvoidmain(String[]args)throwsException{ SumThreadst=newSumThread(1,1000); st.start(); st.join();//主線程main等待st線程結束
System.out.println(st.getSum()); }}結果:500500改進版本4.線程的生命周期新建死亡新建狀態(tài):當一個線程類實例被創(chuàng)立時,線程處于新建狀態(tài),此時的線程已經被初始化,并分配了資源 例如:ThreadmyThread=newMyThreadClass();就緒狀態(tài):已具備運行條件,進入線程隊列,排隊等待CPU。一旦獲得CPU使用權,就可進入運行狀態(tài) 例如:myThread.start();運行狀態(tài):當處于就緒狀態(tài)的線程被調度獲得CPU資源時,就進入了運行狀態(tài)。定義在線程體中的run()方法被調用,從方法體的第一條語句開始順序執(zhí)行;阻塞狀態(tài):處于運行狀態(tài)的線程因事件的發(fā)生,而導致讓出CPU使用權,并終止當前執(zhí)行,進行阻塞狀態(tài)。線程的生命周期有五種狀態(tài): 線程由運行狀態(tài)進入阻塞狀態(tài)包含以下幾種情況:調用了該線程的sleep()方法。等待其休眠指定時間之后,自動脫離阻塞狀態(tài);等待I/O操作完成。一旦I/O操作完成,系統(tǒng)自己調用特定的指令使該線程恢復可運行狀態(tài);調用wait()方法。調用notify()或notifyAll()方法可回到運行狀態(tài);調用suspend()方法。調用resume()方法可恢復線程的執(zhí)行;死亡狀態(tài):線程通過以下兩種途徑進入死亡狀態(tài):自然終止:正常運行run()方法后終止;異常終止:調用stop()方法讓一個線程終止運行。sleep():使一個線程在特定時間休眠,具體格式:publicstaticvoidsleep(longmillisec);(單位:毫秒)publicstaticvoidsleep(longmillisec,intnanosec);
(后一參數(shù)的單位:納秒)yield():將CPU讓予其它線程。這將導致正在運行的線程暫時停止,允許其他線程運行;正在休眠或等待的線程可通過調用interrupt()方法中斷,這會導致拋出一個interruptedException異常;通過isInterrupted()方法,可以了解一個線程是否被中斷;join():調用某線程的該方法,將當前線程與該線程“合并”,即等待該線程結束,再恢復當前線程的運行。5.線程的根本控制例6代碼://線程喚醒的例子publicclassThreadInterruptDemoextendsThread{ publicvoidrun(){ System.out.println("休息,勿擾!"); try{ sleep(3600000); }catch(InterruptedExceptione){ System.out.println("啊,誰叫醒我的?"); } } publicstaticvoidmain(Stringargs[]){
ThreadInterruptDemot=newThreadInterruptDemo(); t.start(); errupt();//喚醒線程 }}程序運行結果休息,勿擾!啊,誰叫醒我的?例7代碼://線程的join()方法publicclassThreadJoinDemoextendsThread{ publicstaticvoidmain(Stringargs[]){
MyRunnermyr=newMyRunner(); Threadt=newThread(myr); t.start(); try{
t.join(); }catch(InterruptedExceptione){ } for(inti=0;i<5;i++){ System.out.println("主線程:"+i); } }}classMyRunnerimplementsRunnable{
publicvoidrun(){ for(inti=0;i<5;i++) System.out.println("子線程:"+i); }}程序運行結果子線程:0子線程:1子線程:2子線程:3子線程:4主線程:0主線程:1主線程:2主線程:3主線程:4//例8線程狀態(tài)轉換publicclassThreadStatusDemo{ publicstaticvoidmain(Stringargs[]){ MyRunnerr=newMyRunner(); Threadt=newThread(r);//新建狀態(tài) t.start();//啟動狀態(tài) }}classMyRunnerimplementsRunnable{
publicvoidrun(){//運行狀態(tài) for(inti=0;i<20;i++){ if(i%5==0&&i!=0){ try{ Thread.sleep(3000);//阻塞狀態(tài) }catch(InterruptedExceptione){ } } System.out.println("No."+i);//運行狀態(tài) } }}程序運行結果(當為5的倍數(shù)時休眠3秒鐘)No.0No.1No.2No.3No.4No.5No.6……No.18No.19線程可以劃分為兩種類型:用戶線程(第1種)由用戶〔程序員〕創(chuàng)立在前臺執(zhí)行當用戶線程運行時,JVM不會退出但在所有用戶線程都執(zhí)行完畢時,JVM將終止所有守護線程(包括垃圾收集器),然后退出主線程是用main()方法創(chuàng)立的6.線程的類型守護線程(第2種):是為其它線程提供效勞的線程,它一般應該是一個獨立的線程,它的run()方法是一個無限循環(huán);它們通常在后臺執(zhí)行,例如:定時器、垃圾回收器都是守護線程;某些用戶創(chuàng)立的線程會通過調用setDaemon()方法在后臺運行。使用守護線程的本卷須知:(1)thread.setDaemon(true)必須在thread.start()之前設置,否那么會跑出一個IllegalThreadStateException異常。不能把正在運行的常規(guī)線程設置為守護線程。
(2)在Daemon線程中產生的新線程也是Daemon的。
(3)局部任務不適合分配給Daemon來進行效勞,比方IIO讀寫。
例9代碼://守護線程的例子publicclassDaemonThreadextendsThread{
publicvoidrun(){ while(true){ System.out.println("守護線程正在運行..."); } } publicstaticvoidmain(Stringargs[]){
DaemonThreaddt=newDaemonThread(); dt.setDaemon(true);//設置為后臺線程 dt.start(); }}程序運行結果守護線程正在運行...守護線程正在運行...守護線程正在運行...守護線程正在運行...守護線程正在運行...…...問題:該線程最終能否自動終止?例10代碼://文件輸出的守護線程任務importjava.io.*;classTestRunnableimplementsRunnable{publicvoidrun(){try{Thread.sleep(1000);//守護線程阻塞1秒后運行
Filef=newFile(“F://daemon.txt");FileOutputStreamos=newFileOutputStream(f,true);os.write("daemon".getBytes());}catch(IOExceptione1){e1.printStackTrace();}catch(InterruptedExceptione2){e2.printStackTrace();}}}例10代碼〔續(xù)〕:publicclassTestDemo2{publicstaticvoidmain(String[]args)throwsInterruptedException{Runnabletr=newTestRunnable();Threadthread=newThread(tr);
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025標準的攝影作品使用許可合同
- 二零二五年度凈水器綠色環(huán)保認證采購合同
- 2025年度文化產業(yè)分紅合作協(xié)議范本(含IP授權)3篇
- 2025年度公司設立前股東合作協(xié)議書(含知識產權保護)3篇
- 2025年度公司股東間應急事件處理合作協(xié)議書3篇
- 2025年度農產品電商平臺農產品物流配送優(yōu)化合同版3篇
- 2025年度農機租賃與農業(yè)科研合作開發(fā)合同3篇
- 二零二五年度農村宅基地租賃及土地流轉服務協(xié)議
- 2025年度農產品深加工項目原料供應合同版3篇
- 二零二五年度婚慶服務市場區(qū)域保護競業(yè)禁止合同2篇
- 國外幼兒園自主游戲研究現(xiàn)狀
- 浙江大學2011–2012學年冬季學期《高級數(shù)據(jù)結構與算法分析》課程期末考試試卷
- 職業(yè)生涯規(guī)劃-體驗式學習智慧樹知到期末考試答案章節(jié)答案2024年華僑大學
- 手術保護性約束
- AQ4230-2013 糧食平房倉粉塵防爆安全規(guī)范
- (正式版)JBT 10437-2024 電線電纜用可交聯(lián)聚乙烯絕緣料
- 建筑節(jié)能與綠色建筑監(jiān)理細則
- 2024法務部門合規(guī)風險管理實踐模板
- 學??蒲刑幪庨L述職報告范文
- 護理文書書寫規(guī)范
- 2023-2024學年安徽省阜陽市臨泉縣八年級(上)期末數(shù)學試卷(含解析)
評論
0/150
提交評論