Java語(yǔ)言程序設(shè)計(jì)第8章課件_第1頁(yè)
Java語(yǔ)言程序設(shè)計(jì)第8章課件_第2頁(yè)
Java語(yǔ)言程序設(shè)計(jì)第8章課件_第3頁(yè)
Java語(yǔ)言程序設(shè)計(jì)第8章課件_第4頁(yè)
Java語(yǔ)言程序設(shè)計(jì)第8章課件_第5頁(yè)
已閱讀5頁(yè),還剩85頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第8章線程鄭莉JAVA語(yǔ)言程序設(shè)計(jì)1第8章線程鄭莉JAVA語(yǔ)言程序設(shè)計(jì)1本講內(nèi)容線程基礎(chǔ)線程的概念Thread類Runnable接口資源共享和線程同步線程間的通信線程的生命周期線程的優(yōu)先級(jí)程序舉例2本講內(nèi)容線程基礎(chǔ)2線程的概念進(jìn)程:程序的一次執(zhí)行線程:一個(gè)進(jìn)程中的多個(gè)控制流通過(guò)多線程,一個(gè)進(jìn)程表面上看同時(shí)可以執(zhí)行一個(gè)以上的任務(wù)——并發(fā)多數(shù)程序設(shè)計(jì)語(yǔ)言不支持并發(fā),支持多線程要借助于操作系統(tǒng)“原語(yǔ)(primitives)”Java是第一個(gè)支持內(nèi)置線程操作的主流編程語(yǔ)言線程基礎(chǔ)3線程的概念進(jìn)程:程序的一次執(zhí)行線程基礎(chǔ)3Thread類簡(jiǎn)介線程類需要繼承Thread類Thread的構(gòu)造函數(shù)

publicThread(StringthreadName)

publicThread()在線程的run方法中編寫(xiě)線程的主要任務(wù)sleep方法使線程休眠interrupt方法中斷一個(gè)運(yùn)行中的線程isAlive方法檢查線程的狀態(tài)setName方法設(shè)置線程名join方法等待線程結(jié)束,以執(zhí)行當(dāng)前線程線程基礎(chǔ)4Thread類簡(jiǎn)介線程類需要繼承Thread類線程基礎(chǔ)例8_1在新線程中計(jì)算整數(shù)的階乘publicclassEx8_1{publicstaticvoidmain(String[]args){System.out.println("mainthreadstarts");FactorialThreadthread=newFactorialThread(10);thread.start();System.out.println("newthreadstarted,mainthreadends");}//endmain}線程基礎(chǔ)5例8_1在新線程中計(jì)算整數(shù)的階乘publicclass//classFactorialThreadcontrolsthreadexecutionclassFactorialThreadextendsThread{privateintnum;publicFactorialThread(intnum){this.num=num;}publicvoidrun(){inti=num;intresult=1;while(i>0){result=result*i; i=i-1;}System.out.println("Thefactorialof"+num+"is"+result);System.out.println("newthreadends");}}6//classFactorialThreadcontr運(yùn)行結(jié)果如下:mainthreadstartsnewthreadstarted,mainthreadendsThefactorialof10is3628800newthreadends7運(yùn)行結(jié)果如下:7例8_2創(chuàng)建3個(gè)新線程,每個(gè)線程睡眠任意0-6秒鐘,然后結(jié)束。publicclassEx8_2{publicstaticvoidmain(String[]args){//創(chuàng)建并命名每個(gè)線程

TestThreadthread1=newTestThread("thread1");TestThreadthread2=newTestThread("thread2");TestThreadthread3=newTestThread("thread3");System.out.println("Startingthreads");thread1.start();//啟動(dòng)線程1thread2.start();//啟動(dòng)線程2thread3.start();//啟動(dòng)線程3System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)8例8_2創(chuàng)建3個(gè)新線程,每個(gè)線程睡眠任意0-6秒鐘,然后結(jié)classTestThreadextendsThread{privateintsleepTime;publicTestThread(Stringname)//構(gòu)造函數(shù)

{super(name);//調(diào)用基類構(gòu)造函數(shù)為線程命名

//獲得隨機(jī)休息毫秒數(shù)

sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(getName()+"finished");

}}9classTestThreadextendsThrea運(yùn)行結(jié)果為:StartingthreadsThreadsstarted,mainendsthread1goingtosleepfor3519thread2goingtosleepfor1689thread3goingtosleepfor5565thread2finishedthread1finishedthread3finished10運(yùn)行結(jié)果為:10Runnable接口如果希望一個(gè)已經(jīng)有基類的類支持多線程,則不能再繼承Thread類了(Java不支持多繼承)解決方法:使類實(shí)現(xiàn)Runnable接口,再與Thread類結(jié)合使用一個(gè)內(nèi)部類提供Runnable的實(shí)現(xiàn)代碼,將內(nèi)部類的對(duì)象與Thread結(jié)合相對(duì)于Thread類,它更適合于多個(gè)線程處理同一資源線程基礎(chǔ)11Runnable接口如果希望一個(gè)已經(jīng)有基類的類支持多線程,則例8_3使用Runnable接口實(shí)現(xiàn)例8_1功能publicclassEx8_1{publicstaticvoidmain(String[]args){System.out.println("mainthreadstarts");FactorialThreadt=newFactorialThread(10);newThread(t).start();System.out.println("newthreadstarted,mainthreadends");}//endmain}線程基礎(chǔ)12例8_3使用Runnable接口實(shí)現(xiàn)例8_1功能publi//classFactorialThreadcontrolsthreadexecutionclassFactorialThreadimplementsRunnable{privateintnum;publicFactorialThread(intnum){this.num=num;}publicvoidrun(){inti=num;intresult=1;while(i>0){result=result*i; i=i-1;}System.out.println("Thefactorialof"+num+"is"+result);System.out.println("newthreadends");}}13//classFactorialThreadcontr例8_4使用Runnable接口實(shí)現(xiàn)例8_2功能publicclassEx8_4{publicstaticvoidmain(String[]args){//創(chuàng)建3個(gè)實(shí)現(xiàn)Runnable接口類的對(duì)象

TestThreadthread1=newTestThread();TestThreadthread2=newTestThread();TestThreadthread3=newTestThread();System.out.println("Startingthreads");//分別以三個(gè)對(duì)象為參數(shù)創(chuàng)建三個(gè)新線程,

//第二個(gè)參數(shù)為新線程命名并啟動(dòng)之

newThread(thread1,"Thread1").start();newThread(thread2,"Thread2").start();newThread(thread3,"Thread3").start();System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)14例8_4使用Runnable接口實(shí)現(xiàn)例8_2功能publiclassTestThreadimplementsRunnable{privateintsleepTime;publicTestThread()//構(gòu)造方法

{//獲得隨機(jī)休息毫秒數(shù)sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(Thread.currentThread().getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(Thread.currentThread().getName()+"finished");

}}15classTestThreadimplementsRu運(yùn)行結(jié)果如下:StartingthreadsThread1goingtosleepfor1487Thread2goingtosleepfor1133Threadsstarted,mainendsThread3goingtosleepfor2328Thread2finishedThread1finishedThread3finished16運(yùn)行結(jié)果如下:16資源共享和線程同步獨(dú)立的同時(shí)運(yùn)行的線程有時(shí)需要共享一些數(shù)據(jù)并且考慮到彼此的狀態(tài)和動(dòng)作。例如生產(chǎn)/消費(fèi)問(wèn)題:生產(chǎn)線程產(chǎn)生數(shù)據(jù)流,然后這些數(shù)據(jù)流再被消費(fèi)線程消費(fèi)。具體來(lái)說(shuō),假設(shè)一個(gè)Java應(yīng)用程序,其中有一個(gè)線程負(fù)責(zé)往文件寫(xiě)數(shù)據(jù),另一個(gè)線程從同一個(gè)文件中往出都數(shù)據(jù),因?yàn)樯婕暗酵粋€(gè)資源,這里是同一個(gè)文件,這兩個(gè)線程必須保證某種方式的同步。當(dāng)多個(gè)線程的執(zhí)行代碼來(lái)自同一個(gè)類的實(shí)例(若干個(gè))時(shí),即稱它們共享相同的代碼,當(dāng)共享訪問(wèn)相同的對(duì)象時(shí),即它們共享相同的數(shù)據(jù)。使用Runnable接口可以輕松實(shí)現(xiàn)多個(gè)線程共享相同數(shù)據(jù),只要用同一個(gè)實(shí)現(xiàn)了Runnable接口的實(shí)例作為參數(shù)創(chuàng)建多個(gè)線程就可以了。線程基礎(chǔ)17資源共享和線程同步獨(dú)立的同時(shí)運(yùn)行的線程有時(shí)需要共享一些數(shù)據(jù)并例8_5修改例8_4//只用一個(gè)Runnable類型的對(duì)象為參數(shù)創(chuàng)建3個(gè)新線程。publicclassEx8_5{publicstaticvoidmain(String[]args){//只創(chuàng)建1個(gè)實(shí)現(xiàn)Runnable接口類的對(duì)象

TestThreadthread=newTestThread();System.out.println("Startingthreads");//只用一個(gè)Runnable類型對(duì)象為參數(shù)創(chuàng)建三個(gè)新線程,

//命名并啟動(dòng)之

newThread(thread,"Thread1").start();newThread(thread,"Thread2").start();newThread(thread,"Thread3").start();System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)18例8_5修改例8_4//只用一個(gè)Runnable類型的對(duì)象classTestThreadimplementsRunnable{privateintsleepTime;publicTestThread()//構(gòu)造函數(shù)

{//獲得隨機(jī)休息毫秒數(shù)sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(Thread.currentThread().getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(Thread.currentThread().getName()+"finished");

}}19classTestThreadimplementsRuStartingthreadsThread1goingtosleepfor966Thread2goingtosleepfor966Threadsstarted,mainendsThread3goingtosleepfor966Thread1finishedThread2finishedThread3finished20Startingthreads20例8_6用三個(gè)線程模擬三個(gè)售票口,總共出售200張票。publicclassEx8_6{ publicstaticvoidmain(String[]args) {//新建一個(gè)售票類的對(duì)象 SellTicketst=newSellTickets();//用此對(duì)象作為參數(shù)創(chuàng)建3個(gè)新線程并啟動(dòng)

newThread(t).start();

newThread(t).start(); newThread(t).start(); }}線程基礎(chǔ)21例8_6用三個(gè)線程模擬三個(gè)售票口,總共出售200張票。puclassSellTicketsimplementsRunnable{ //將共享的資源作為私有變量privateinttickets=200;

publicvoidrun() { while(tickets>0)//直到?jīng)]有票可售為止

{ System.out.println(Thread.currentThread().getName()+ "issellingticket"+tickets--); } }}22classSellTicketsimplementsR例8_7用兩個(gè)線程模擬存票、賣票過(guò)程publicclassEx8_7{ publicstaticvoidmain(String[]args) {//新建一個(gè)票類對(duì)象,總票數(shù)作為參數(shù) Ticketst=newTickets(10);

//以票類對(duì)象為參數(shù)創(chuàng)建存票線程對(duì)象,并啟動(dòng)newProducer(t).start();

//以同一個(gè)票類對(duì)象為參數(shù)創(chuàng)建售票線程,并啟動(dòng)newConsumer(t).start();

}}線程基礎(chǔ)23例8_7用兩個(gè)線程模擬存票、賣票過(guò)程publicclasclassTickets//票類{ intnumber=0;//票號(hào)

intsize;//總票數(shù)//表示目前是否有票可售

booleanavailable=false;//構(gòu)造方法,傳入總票數(shù)參數(shù) publicTickets(intsize)

{ this.size=size; } }24classTickets//票類24classProducerextendsThread//存票線程{ Ticketst=null; publicProducer(Ticketst)//構(gòu)造函數(shù)以一個(gè)票類對(duì)象為參數(shù)

{this.t=t;} publicvoidrun() {//限制循環(huán)條件為存票序號(hào)小于總票數(shù) while((t.number)<t.size){ System.out.println("Producerputsticket"+(++t.number)); t.available=true;//可以賣票

} }}25classProducerextendsThreadclassConsumerextendsThread//售票線程{ Ticketst=null; inti=0; publicConsumer(Ticketst)//構(gòu)造函數(shù)以一個(gè)票類對(duì)象為參數(shù)

{this.t=t; } publicvoidrun() {while(i<t.size)//循環(huán)條件為售票序號(hào)小于總票數(shù)

{ if(t.available==true&&i<=t.number)//有票且小于目前票序號(hào)

System.out.println("Consumerbuysticket"+(++i)); if(i==t.number)//如果票已售到當(dāng)前序號(hào),則不可售

t.available=false; } }}26classConsumerextendsThread運(yùn)行結(jié)果Producerputsticket1Producerputsticket2Producerputsticket3Producerputsticket4Producerputsticket5Producerputsticket6Producerputsticket7Producerputsticket8Consumerbuysticket1Consumerbuysticket2Consumerbuysticket3Consumerbuysticket4Consumerbuysticket5Consumerbuysticket6Consumerbuysticket7Consumerbuysticket8Producerputsticket9Producerputsticket10死機(jī)(進(jìn)入死循環(huán))27運(yùn)行結(jié)果27錯(cuò)誤原因假如售票線程運(yùn)行到t.available=false之前,CPU切換到執(zhí)行存票線程,存票線程將available置為true,但再次切換到售票線程后,售票線程執(zhí)行t.available=false,則由于售票號(hào)目前還是8,小于總票數(shù),且存票線程已經(jīng)結(jié)束不再能將t.available置為true,則售票線程陷入了死循環(huán)。線程基礎(chǔ)28錯(cuò)誤原因假如售票線程運(yùn)行到t.available=false線程同步(Synchronization)Java使用的同步機(jī)制是監(jiān)視器,支持線程的互斥與同步互斥:許多線程在同一個(gè)共享數(shù)據(jù)上操作而互不干擾,同一時(shí)刻只能有一個(gè)線程訪問(wèn)該共享數(shù)據(jù)。因此有些方法或程序段在同一時(shí)刻只能被一個(gè)線程執(zhí)行,稱之為監(jiān)視區(qū)。協(xié)作:多個(gè)線程可以有條件地同時(shí)操作共享數(shù)據(jù)執(zhí)行監(jiān)視區(qū)代碼的線程在條件滿足的情況下可以允許其它線程進(jìn)入監(jiān)視區(qū)。線程基礎(chǔ)29線程同步(Synchronization)Java使用的同線程間的通信線程同步關(guān)鍵字——synchronized用于指定需要同步的代碼段或方法,也就是監(jiān)視區(qū)。wait(

)當(dāng)前狀態(tài)不適合本線程執(zhí)行時(shí),進(jìn)入等待狀態(tài)notify()隨機(jī)喚醒一個(gè)等待的線程,本線程繼續(xù)執(zhí)行。notifyAll()喚醒所有等待的線程,本線程繼續(xù)執(zhí)行。線程基礎(chǔ)30線程間的通信線程同步關(guān)鍵字——synchronized線程線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,這期間關(guān)鍵數(shù)據(jù)仍可能被改變。被喚醒線程的線程可能有多個(gè)。(使用notifyAll時(shí))。被喚醒的線程開(kāi)始執(zhí)行時(shí),一定要判斷當(dāng)前狀態(tài)是否適合自己運(yùn)行。線程基礎(chǔ)31線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,例8_8實(shí)現(xiàn)例8_7功能。將同步方法放在共享的資源類Tickets中。publicclassEx8_8{ publicstaticvoidmain(String[]args) { Ticketst=newTickets(10); newProducer(t).start(); newConsumer(t).start(); }}線程基礎(chǔ)32例8_8實(shí)現(xiàn)例8_7功能。將同步方法放在共享的資源類TicclassTickets{intsize;//票總數(shù)intnumber=0;//存票序號(hào)inti=0;//售票序號(hào)booleanavailable=false;//是否有待售的票publicTickets(intsize){this.size=size;}publicsynchronizedvoidput()//同步代碼塊,實(shí)現(xiàn)存票的功能{System.out.println("Producerputsticket"+(++number));available=true; } publicsynchronizedvoidsell()//同步代碼塊,實(shí)現(xiàn)售票的功能{if(available==true&&i<=number) System.out.println("Consumerbuysticket"+(++i));if(i==number)available=false; } }33classTickets33classConsumerextendsThread{Ticketst=null;//構(gòu)造方法,使兩線程共享票類對(duì)象publicConsumer(Ticketst){this.t=t;}publicvoidrun()//如果售票數(shù)小于限定總量,則不斷售票{while(t.i<t.size)

t.sell();}}34classConsumerextendsThread3例8_9每存入一張票,就售一張票,售出后,再存入publicclassEx8_8{ publicstaticvoidmain(String[]args) { Ticketst=newTickets(10); newProducer(t).start(); newConsumer(t).start(); }}線程基礎(chǔ)35例8_9每存入一張票,就售一張票,售出后,再存入publiclassTickets{ intsize; intnumber=0; inti=0; booleanavailable=false; publicTickets(intsize) {this.size=size;} publicsynchronizedvoidput() {if(available)//如果還有存票待售,則存票線程等待

try{wait();}catch(Exceptione){} System.out.println("Producerputsticket"+(++number)); available=true; notify(); ...//存票后喚醒售票線程開(kāi)始售票

} 36classTickets36

publicsynchronizedvoidsell() {if(!available)//如果沒(méi)有存票,則售票線程等待

try{wait();}catch(Exceptione){} if(i<=number)System.out.println("Consumerbuysticket"+(++i));if(i==number) {try{Thread.sleep(1);}catch(Exceptione){} available=false; } notify();//售票后喚醒存票線程開(kāi)始存票

} }37 publicsynchronizedvoidsellclassProducerextendsThread{ Ticketst=null; publicProducer(Ticketst) { this.t=t; } publicvoidrun() { while(t.number<t.size) t.put(); } }38classProducerextendsThread3classConsumerextendsThread{ Ticketst=null; publicConsumer(Ticketst) { this.t=t; } publicvoidrun() { while(t.i<t.size) t.sell(); } }39classConsumerextendsThread3運(yùn)行結(jié)果如下:Producerputsticket1Consumerbuysticket1Producerputsticket2Consumerbuysticket2Producerputsticket3Consumerbuysticket3Producerputsticket4Consumerbuysticket4Producerputsticket5Consumerbuysticket5Producerputsticket6Consumerbuysticket6Producerputsticket7Consumerbuysticket7Producerputsticket8Consumerbuysticket8Producerputsticket9Consumerbuysticket9Producerputsticket10Consumerbuysticket1040運(yùn)行結(jié)果如下:40守護(hù)(Daemon)線程為了輔助其它線程而運(yùn)行的線程不妨礙程序終止“垃圾回收”便是一個(gè)守護(hù)線程用setDaemon方法將線程設(shè)置為守護(hù)線程線程基礎(chǔ)41守護(hù)(Daemon)線程為了輔助其它線程而運(yùn)行的線程線程例8_10創(chuàng)建一個(gè)無(wú)限循環(huán)的守護(hù)線程publicclassEx8_10{ publicstaticvoidmain(String[]args) { ThreadTestt=newThreadTest(); t.setDaemon(true); t.start(); }}classThreadTestextendsThread{ publicvoidrun() { while(true){}}}42例8_10創(chuàng)建一個(gè)無(wú)限循環(huán)的守護(hù)線程publicclas線程的狀態(tài)誕生狀態(tài)線程剛剛被創(chuàng)建就緒狀態(tài)線程的start方法已被執(zhí)行線程已準(zhǔn)備好運(yùn)行運(yùn)行狀態(tài)處理機(jī)分配給了線程,線程正在運(yùn)行阻塞狀態(tài)(Blocked)在線程發(fā)出輸入/輸出請(qǐng)求且必須等待其返回,或遇到用synchronized標(biāo)記的方法而未獲得其監(jiān)視器暫時(shí)不能進(jìn)入執(zhí)行時(shí)休眠狀態(tài)(Sleeping)執(zhí)行sleep方法而進(jìn)入休眠死亡狀態(tài)線程已完成或退出線程的生命周期43線程的狀態(tài)誕生狀態(tài)線程的生命周期434444線程優(yōu)先級(jí)與調(diào)度Java線程優(yōu)先級(jí)(priority)取值范圍1-10時(shí)間片(Timeslicing)每個(gè)線程被賦予一定的處理機(jī)時(shí)間總是調(diào)度最高優(yōu)先級(jí)的線程運(yùn)行45線程優(yōu)先級(jí)與調(diào)度Java線程優(yōu)先級(jí)(priority)第8章線程鄭莉JAVA語(yǔ)言程序設(shè)計(jì)46第8章線程鄭莉JAVA語(yǔ)言程序設(shè)計(jì)1本講內(nèi)容線程基礎(chǔ)線程的概念Thread類Runnable接口資源共享和線程同步線程間的通信線程的生命周期線程的優(yōu)先級(jí)程序舉例47本講內(nèi)容線程基礎(chǔ)2線程的概念進(jìn)程:程序的一次執(zhí)行線程:一個(gè)進(jìn)程中的多個(gè)控制流通過(guò)多線程,一個(gè)進(jìn)程表面上看同時(shí)可以執(zhí)行一個(gè)以上的任務(wù)——并發(fā)多數(shù)程序設(shè)計(jì)語(yǔ)言不支持并發(fā),支持多線程要借助于操作系統(tǒng)“原語(yǔ)(primitives)”Java是第一個(gè)支持內(nèi)置線程操作的主流編程語(yǔ)言線程基礎(chǔ)48線程的概念進(jìn)程:程序的一次執(zhí)行線程基礎(chǔ)3Thread類簡(jiǎn)介線程類需要繼承Thread類Thread的構(gòu)造函數(shù)

publicThread(StringthreadName)

publicThread()在線程的run方法中編寫(xiě)線程的主要任務(wù)sleep方法使線程休眠interrupt方法中斷一個(gè)運(yùn)行中的線程isAlive方法檢查線程的狀態(tài)setName方法設(shè)置線程名join方法等待線程結(jié)束,以執(zhí)行當(dāng)前線程線程基礎(chǔ)49Thread類簡(jiǎn)介線程類需要繼承Thread類線程基礎(chǔ)例8_1在新線程中計(jì)算整數(shù)的階乘publicclassEx8_1{publicstaticvoidmain(String[]args){System.out.println("mainthreadstarts");FactorialThreadthread=newFactorialThread(10);thread.start();System.out.println("newthreadstarted,mainthreadends");}//endmain}線程基礎(chǔ)50例8_1在新線程中計(jì)算整數(shù)的階乘publicclass//classFactorialThreadcontrolsthreadexecutionclassFactorialThreadextendsThread{privateintnum;publicFactorialThread(intnum){this.num=num;}publicvoidrun(){inti=num;intresult=1;while(i>0){result=result*i; i=i-1;}System.out.println("Thefactorialof"+num+"is"+result);System.out.println("newthreadends");}}51//classFactorialThreadcontr運(yùn)行結(jié)果如下:mainthreadstartsnewthreadstarted,mainthreadendsThefactorialof10is3628800newthreadends52運(yùn)行結(jié)果如下:7例8_2創(chuàng)建3個(gè)新線程,每個(gè)線程睡眠任意0-6秒鐘,然后結(jié)束。publicclassEx8_2{publicstaticvoidmain(String[]args){//創(chuàng)建并命名每個(gè)線程

TestThreadthread1=newTestThread("thread1");TestThreadthread2=newTestThread("thread2");TestThreadthread3=newTestThread("thread3");System.out.println("Startingthreads");thread1.start();//啟動(dòng)線程1thread2.start();//啟動(dòng)線程2thread3.start();//啟動(dòng)線程3System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)53例8_2創(chuàng)建3個(gè)新線程,每個(gè)線程睡眠任意0-6秒鐘,然后結(jié)classTestThreadextendsThread{privateintsleepTime;publicTestThread(Stringname)//構(gòu)造函數(shù)

{super(name);//調(diào)用基類構(gòu)造函數(shù)為線程命名

//獲得隨機(jī)休息毫秒數(shù)

sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(getName()+"finished");

}}54classTestThreadextendsThrea運(yùn)行結(jié)果為:StartingthreadsThreadsstarted,mainendsthread1goingtosleepfor3519thread2goingtosleepfor1689thread3goingtosleepfor5565thread2finishedthread1finishedthread3finished55運(yùn)行結(jié)果為:10Runnable接口如果希望一個(gè)已經(jīng)有基類的類支持多線程,則不能再繼承Thread類了(Java不支持多繼承)解決方法:使類實(shí)現(xiàn)Runnable接口,再與Thread類結(jié)合使用一個(gè)內(nèi)部類提供Runnable的實(shí)現(xiàn)代碼,將內(nèi)部類的對(duì)象與Thread結(jié)合相對(duì)于Thread類,它更適合于多個(gè)線程處理同一資源線程基礎(chǔ)56Runnable接口如果希望一個(gè)已經(jīng)有基類的類支持多線程,則例8_3使用Runnable接口實(shí)現(xiàn)例8_1功能publicclassEx8_1{publicstaticvoidmain(String[]args){System.out.println("mainthreadstarts");FactorialThreadt=newFactorialThread(10);newThread(t).start();System.out.println("newthreadstarted,mainthreadends");}//endmain}線程基礎(chǔ)57例8_3使用Runnable接口實(shí)現(xiàn)例8_1功能publi//classFactorialThreadcontrolsthreadexecutionclassFactorialThreadimplementsRunnable{privateintnum;publicFactorialThread(intnum){this.num=num;}publicvoidrun(){inti=num;intresult=1;while(i>0){result=result*i; i=i-1;}System.out.println("Thefactorialof"+num+"is"+result);System.out.println("newthreadends");}}58//classFactorialThreadcontr例8_4使用Runnable接口實(shí)現(xiàn)例8_2功能publicclassEx8_4{publicstaticvoidmain(String[]args){//創(chuàng)建3個(gè)實(shí)現(xiàn)Runnable接口類的對(duì)象

TestThreadthread1=newTestThread();TestThreadthread2=newTestThread();TestThreadthread3=newTestThread();System.out.println("Startingthreads");//分別以三個(gè)對(duì)象為參數(shù)創(chuàng)建三個(gè)新線程,

//第二個(gè)參數(shù)為新線程命名并啟動(dòng)之

newThread(thread1,"Thread1").start();newThread(thread2,"Thread2").start();newThread(thread3,"Thread3").start();System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)59例8_4使用Runnable接口實(shí)現(xiàn)例8_2功能publiclassTestThreadimplementsRunnable{privateintsleepTime;publicTestThread()//構(gòu)造方法

{//獲得隨機(jī)休息毫秒數(shù)sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(Thread.currentThread().getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(Thread.currentThread().getName()+"finished");

}}60classTestThreadimplementsRu運(yùn)行結(jié)果如下:StartingthreadsThread1goingtosleepfor1487Thread2goingtosleepfor1133Threadsstarted,mainendsThread3goingtosleepfor2328Thread2finishedThread1finishedThread3finished61運(yùn)行結(jié)果如下:16資源共享和線程同步獨(dú)立的同時(shí)運(yùn)行的線程有時(shí)需要共享一些數(shù)據(jù)并且考慮到彼此的狀態(tài)和動(dòng)作。例如生產(chǎn)/消費(fèi)問(wèn)題:生產(chǎn)線程產(chǎn)生數(shù)據(jù)流,然后這些數(shù)據(jù)流再被消費(fèi)線程消費(fèi)。具體來(lái)說(shuō),假設(shè)一個(gè)Java應(yīng)用程序,其中有一個(gè)線程負(fù)責(zé)往文件寫(xiě)數(shù)據(jù),另一個(gè)線程從同一個(gè)文件中往出都數(shù)據(jù),因?yàn)樯婕暗酵粋€(gè)資源,這里是同一個(gè)文件,這兩個(gè)線程必須保證某種方式的同步。當(dāng)多個(gè)線程的執(zhí)行代碼來(lái)自同一個(gè)類的實(shí)例(若干個(gè))時(shí),即稱它們共享相同的代碼,當(dāng)共享訪問(wèn)相同的對(duì)象時(shí),即它們共享相同的數(shù)據(jù)。使用Runnable接口可以輕松實(shí)現(xiàn)多個(gè)線程共享相同數(shù)據(jù),只要用同一個(gè)實(shí)現(xiàn)了Runnable接口的實(shí)例作為參數(shù)創(chuàng)建多個(gè)線程就可以了。線程基礎(chǔ)62資源共享和線程同步獨(dú)立的同時(shí)運(yùn)行的線程有時(shí)需要共享一些數(shù)據(jù)并例8_5修改例8_4//只用一個(gè)Runnable類型的對(duì)象為參數(shù)創(chuàng)建3個(gè)新線程。publicclassEx8_5{publicstaticvoidmain(String[]args){//只創(chuàng)建1個(gè)實(shí)現(xiàn)Runnable接口類的對(duì)象

TestThreadthread=newTestThread();System.out.println("Startingthreads");//只用一個(gè)Runnable類型對(duì)象為參數(shù)創(chuàng)建三個(gè)新線程,

//命名并啟動(dòng)之

newThread(thread,"Thread1").start();newThread(thread,"Thread2").start();newThread(thread,"Thread3").start();System.out.println("Threadsstarted,mainends\n");}}線程基礎(chǔ)63例8_5修改例8_4//只用一個(gè)Runnable類型的對(duì)象classTestThreadimplementsRunnable{privateintsleepTime;publicTestThread()//構(gòu)造函數(shù)

{//獲得隨機(jī)休息毫秒數(shù)sleepTime=(int)(Math.random()*6000);

}publicvoidrun()//線程啟動(dòng)并開(kāi)始運(yùn)行后要執(zhí)行的方法

{try{System.out.println(Thread.currentThread().getName()+"goingtosleepfor"+sleepTime);Thread.sleep(sleepTime);//線程休眠

}catch(InterruptedExceptionexception){};//運(yùn)行結(jié)束,給出提示信息System.out.println(Thread.currentThread().getName()+"finished");

}}64classTestThreadimplementsRuStartingthreadsThread1goingtosleepfor966Thread2goingtosleepfor966Threadsstarted,mainendsThread3goingtosleepfor966Thread1finishedThread2finishedThread3finished65Startingthreads20例8_6用三個(gè)線程模擬三個(gè)售票口,總共出售200張票。publicclassEx8_6{ publicstaticvoidmain(String[]args) {//新建一個(gè)售票類的對(duì)象 SellTicketst=newSellTickets();//用此對(duì)象作為參數(shù)創(chuàng)建3個(gè)新線程并啟動(dòng)

newThread(t).start();

newThread(t).start(); newThread(t).start(); }}線程基礎(chǔ)66例8_6用三個(gè)線程模擬三個(gè)售票口,總共出售200張票。puclassSellTicketsimplementsRunnable{ //將共享的資源作為私有變量privateinttickets=200;

publicvoidrun() { while(tickets>0)//直到?jīng)]有票可售為止

{ System.out.println(Thread.currentThread().getName()+ "issellingticket"+tickets--); } }}67classSellTicketsimplementsR例8_7用兩個(gè)線程模擬存票、賣票過(guò)程publicclassEx8_7{ publicstaticvoidmain(String[]args) {//新建一個(gè)票類對(duì)象,總票數(shù)作為參數(shù) Ticketst=newTickets(10);

//以票類對(duì)象為參數(shù)創(chuàng)建存票線程對(duì)象,并啟動(dòng)newProducer(t).start();

//以同一個(gè)票類對(duì)象為參數(shù)創(chuàng)建售票線程,并啟動(dòng)newConsumer(t).start();

}}線程基礎(chǔ)68例8_7用兩個(gè)線程模擬存票、賣票過(guò)程publicclasclassTickets//票類{ intnumber=0;//票號(hào)

intsize;//總票數(shù)//表示目前是否有票可售

booleanavailable=false;//構(gòu)造方法,傳入總票數(shù)參數(shù) publicTickets(intsize)

{ this.size=size; } }69classTickets//票類24classProducerextendsThread//存票線程{ Ticketst=null; publicProducer(Ticketst)//構(gòu)造函數(shù)以一個(gè)票類對(duì)象為參數(shù)

{this.t=t;} publicvoidrun() {//限制循環(huán)條件為存票序號(hào)小于總票數(shù) while((t.number)<t.size){ System.out.println("Producerputsticket"+(++t.number)); t.available=true;//可以賣票

} }}70classProducerextendsThreadclassConsumerextendsThread//售票線程{ Ticketst=null; inti=0; publicConsumer(Ticketst)//構(gòu)造函數(shù)以一個(gè)票類對(duì)象為參數(shù)

{this.t=t; } publicvoidrun() {while(i<t.size)//循環(huán)條件為售票序號(hào)小于總票數(shù)

{ if(t.available==true&&i<=t.number)//有票且小于目前票序號(hào)

System.out.println("Consumerbuysticket"+(++i)); if(i==t.number)//如果票已售到當(dāng)前序號(hào),則不可售

t.available=false; } }}71classConsumerextendsThread運(yùn)行結(jié)果Producerputsticket1Producerputsticket2Producerputsticket3Producerputsticket4Producerputsticket5Producerputsticket6Producerputsticket7Producerputsticket8Consumerbuysticket1Consumerbuysticket2Consumerbuysticket3Consumerbuysticket4Consumerbuysticket5Consumerbuysticket6Consumerbuysticket7Consumerbuysticket8Producerputsticket9Producerputsticket10死機(jī)(進(jìn)入死循環(huán))72運(yùn)行結(jié)果27錯(cuò)誤原因假如售票線程運(yùn)行到t.available=false之前,CPU切換到執(zhí)行存票線程,存票線程將available置為true,但再次切換到售票線程后,售票線程執(zhí)行t.available=false,則由于售票號(hào)目前還是8,小于總票數(shù),且存票線程已經(jīng)結(jié)束不再能將t.available置為true,則售票線程陷入了死循環(huán)。線程基礎(chǔ)73錯(cuò)誤原因假如售票線程運(yùn)行到t.available=false線程同步(Synchronization)Java使用的同步機(jī)制是監(jiān)視器,支持線程的互斥與同步互斥:許多線程在同一個(gè)共享數(shù)據(jù)上操作而互不干擾,同一時(shí)刻只能有一個(gè)線程訪問(wèn)該共享數(shù)據(jù)。因此有些方法或程序段在同一時(shí)刻只能被一個(gè)線程執(zhí)行,稱之為監(jiān)視區(qū)。協(xié)作:多個(gè)線程可以有條件地同時(shí)操作共享數(shù)據(jù)執(zhí)行監(jiān)視區(qū)代碼的線程在條件滿足的情況下可以允許其它線程進(jìn)入監(jiān)視區(qū)。線程基礎(chǔ)74線程同步(Synchronization)Java使用的同線程間的通信線程同步關(guān)鍵字——synchronized用于指定需要同步的代碼段或方法,也就是監(jiān)視區(qū)。wait(

)當(dāng)前狀態(tài)不適合本線程執(zhí)行時(shí),進(jìn)入等待狀態(tài)notify()隨機(jī)喚醒一個(gè)等待的線程,本線程繼續(xù)執(zhí)行。notifyAll()喚醒所有等待的線程,本線程繼續(xù)執(zhí)行。線程基礎(chǔ)75線程間的通信線程同步關(guān)鍵字——synchronized線程線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,這期間關(guān)鍵數(shù)據(jù)仍可能被改變。被喚醒線程的線程可能有多個(gè)。(使用notifyAll時(shí))。被喚醒的線程開(kāi)始執(zhí)行時(shí),一定要判斷當(dāng)前狀態(tài)是否適合自己運(yùn)行。線程基礎(chǔ)76線程間的通信線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,例8_8實(shí)現(xiàn)例8_7功能。將同步方法放在共享的資源類Tickets中。publicclassEx8_8{ publicstaticvoidmain(String[]args) { Ticketst=newTickets(10); newProducer(t).start(); newConsumer(t).start(); }}線程基礎(chǔ)77例8_8實(shí)現(xiàn)例8_7功能。將同步方法放在共享的資源類TicclassTickets{intsize;//票總數(shù)intnumber=0;//存票序號(hào)inti=0;//售票序號(hào)booleanavailable=false;//是否有待售的票publicTickets(intsize){this.size=size;}publicsynchronizedvoidput()//同步代碼塊,實(shí)現(xiàn)存票的功能{System.out.println("Producerputsticket"+(++number));available=true; } publicsynchronizedvoidsell()//同步代碼塊,實(shí)現(xiàn)售票的功能{if(available==true&&i<=number) System.out.println("Consumerbuysticket"+(++i));if(i==number)available=false; } }78classTickets33classConsumere

溫馨提示

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

評(píng)論

0/150

提交評(píng)論