多線程補(bǔ)充案例_第1頁(yè)
多線程補(bǔ)充案例_第2頁(yè)
多線程補(bǔ)充案例_第3頁(yè)
多線程補(bǔ)充案例_第4頁(yè)
多線程補(bǔ)充案例_第5頁(yè)
已閱讀5頁(yè),還剩13頁(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)介

1、第五章 補(bǔ)充案例案例5-1 繼承Thread類創(chuàng)建多線程一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105002名 稱:繼承Thread類創(chuàng)建多線程2、 練習(xí)目標(biāo)Ø 掌握如何通過(guò)繼承Thread類實(shí)現(xiàn)多線程的創(chuàng)建。Ø 掌握Thread類中run()方法和start()方法的使用。3、 需求分析在程序開發(fā)中,會(huì)遇到一個(gè)功能需要多個(gè)線程同時(shí)執(zhí)行才能完成的情況。這時(shí),可以通過(guò)繼承線程類Thread,并重寫Thread類中的run()方法來(lái)實(shí)現(xiàn)。為了讓初學(xué)者熟悉如何創(chuàng)建多線程,在案例中將通過(guò)繼承Thread類方式創(chuàng)建線程,并實(shí)現(xiàn)多線程分別打印099的數(shù)字的功能。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原

2、理)1) 自定義一個(gè)類Demo,使其繼承Thread類。2) 在Demo類中重寫run()方法,在run()方法內(nèi)編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打?。骸癉emo:”+當(dāng)前循環(huán)次數(shù)。3) 編寫測(cè)試類Example01,在Example01類的main()方法中,創(chuàng)建一個(gè)Demo對(duì)象,并執(zhí)行其 start()方法,接著編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打?。骸癿ain:”+當(dāng)前循環(huán)次數(shù)。二、案例實(shí)現(xiàn)class Demo extends Thread public void run() for (int x = 0; x < 100; x+) System.out.println("Demo

3、:"+x); public class Example01public static void main(String args) Demo d = new Demo();d.start();for(int x=0; x<100; x+)System.out.println("main:"+x); 運(yùn)行結(jié)果如圖5-1所示。圖5-1 運(yùn)行結(jié)果三、案例總結(jié)1、通過(guò)繼承Thread類,并重寫Thread類中的run()方法可以實(shí)現(xiàn)多線程。2、Thread類中,提供的start()方法用于啟動(dòng)新線程,線程啟動(dòng)后,系統(tǒng)會(huì)自動(dòng)調(diào)用run()方法。3、main()方法中有

4、一條主線程在運(yùn)行。案例5-2 實(shí)現(xiàn)Runnable接口創(chuàng)建多線程一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105003名 稱:實(shí)現(xiàn)Runnable接口創(chuàng)建多線程2、 練習(xí)目標(biāo)Ø 掌握如何通過(guò)實(shí)現(xiàn)Runnable接口方式創(chuàng)建多線程。Ø 掌握如何使用Thread類的有參構(gòu)造方法創(chuàng)建Thread對(duì)象。3、 需求分析在Java中只支持單繼承,因此通過(guò)繼承Thread類創(chuàng)建線程有一定的局限性,這時(shí)可以使用另一種方式,即實(shí)現(xiàn)Runnable接口來(lái)創(chuàng)建線程。通過(guò)這種方式需要在Thread(Runnable target)的構(gòu)造方法中,傳遞一個(gè)實(shí)現(xiàn)了Runnable接口的實(shí)例對(duì)象。接下來(lái)在

5、案例中將通過(guò)實(shí)現(xiàn)Runnable接口方式創(chuàng)建線程,并實(shí)現(xiàn)多線程分別打印099的數(shù)字的功能。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Demo,使其實(shí)現(xiàn)Runnable接口。2) 在Demo類中覆寫run()方法,在方法編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打?。寒?dāng)前線程名稱:+當(dāng)前循環(huán)次數(shù)。3) 編寫測(cè)試類Example02,在Example02類的main()方法中,創(chuàng)建一個(gè)Demo對(duì)象,利用Thread(Runnable target)構(gòu)造方法創(chuàng)建2個(gè)線程對(duì)象,分別命名為“蜘蛛俠”和“鋼鐵俠”,并執(zhí)行線程對(duì)象的start()方法,同時(shí)編寫for循環(huán),循環(huán)內(nèi)打印“main:”+當(dāng)前循環(huán)次數(shù)。二、案例

6、實(shí)現(xiàn)class Demo implements Runnable public void run() for(int x=0; x<100; x+)System.out.println(Thread.currentThread().getName()+":"+x); public class Example02 public static void main(String args) Demo d = new Demo();Thread t1 = new Thread(d,"蜘蛛俠");Thread t2 = new Thread(d,"

7、鋼鐵俠");t1.start();t2.start();for (int x = 0; x < 100; x+) System.out.println("main:" + x);運(yùn)行結(jié)果如圖5-2所示。圖5-2 運(yùn)行結(jié)果三、案例總結(jié)1、可以把實(shí)現(xiàn)了Runnable接口并重寫run()方法的實(shí)例對(duì)象,作為Thread有參構(gòu)造方法的參數(shù)來(lái)創(chuàng)建多線程程序。2、使用Thread類的構(gòu)造方法Thread(Runnable target, String name)創(chuàng)建線程對(duì)象時(shí),還可以給線程指定新名稱。3、思考一下:既然有了繼承Thread類的方式,

8、為什么還要有實(shí)現(xiàn)Runnable接口的方式?a) 可以避免由于Java的單繼承帶來(lái)的局限性。在開發(fā)中經(jīng)常碰到這樣一種情況,就是使用一個(gè)已經(jīng)繼承了某一個(gè)類的子類創(chuàng)建線程,由于一個(gè)類不能同時(shí)有兩個(gè)父類,所以不能用繼承Thread類的方式,那么就只能采用實(shí)現(xiàn)Runnable接口的方式。b) 實(shí)現(xiàn)接口的方式,適合多個(gè)相同程序代碼的線程去處理同一個(gè)資源的情況,把線程同程序代碼、數(shù)據(jù)有效的分離,很好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想。例如:一個(gè)售票程序繼承了Thread類,在售票時(shí)啟動(dòng)了多個(gè)售票程序,但他們不是同一個(gè)對(duì)象,數(shù)據(jù)沒(méi)有共享,這樣就會(huì)出現(xiàn)票數(shù)重復(fù)出售的情況;而當(dāng)售票程序?qū)崿F(xiàn)Runnable接口后,多個(gè)線

9、程運(yùn)行同一個(gè)售票程序,實(shí)現(xiàn)了票數(shù)共享的好處。案例5-3 設(shè)置后臺(tái)線程一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105005名 稱:后臺(tái)線程2、 練習(xí)目標(biāo)Ø 了解后臺(tái)線程的生命周期Ø 掌握如何將線程設(shè)置為后臺(tái)線程3、 需求分析默認(rèn)情況下,新創(chuàng)建的線程都是前臺(tái)線程,若想使前臺(tái)線程變?yōu)楹笈_(tái)線程,可以使用setDaemon(true)方法實(shí)現(xiàn),為了讓初學(xué)者熟悉后臺(tái)線程,案例中將通過(guò)設(shè)置一個(gè)后臺(tái)線程并演示后臺(tái)線程和程序結(jié)束之間的關(guān)系。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Watcher,使其實(shí)現(xiàn)Runnable接口。2) 在Watcher類中覆寫run()方法,在方法內(nèi)編寫一個(gè)

10、for循環(huán),循環(huán)體內(nèi)打?。壕€程名稱+循環(huán)次數(shù)。3) 編寫測(cè)試類Example03,在Example03類的main()方法中,創(chuàng)建一個(gè)Watcher對(duì)象,利用Thread(Runnable target)構(gòu)造方法創(chuàng)建線程對(duì)象并命名,將線程設(shè)置為后臺(tái)線程,執(zhí)行該線程的start()方法,接著編寫一個(gè)for循環(huán),循環(huán)內(nèi)打印循環(huán)次數(shù)。二、案例實(shí)現(xiàn)class Watcher implements Runnable public void run() for (int x = 0; x < 1000; x+) System.out.println("我是"+Thread.cur

11、rentThread().getName() +"守護(hù)者,"+"我在守護(hù)雅典娜"+x);public class Example03 public static void main(String args) Watcher watcher = new Watcher();Thread t = new Thread(watcher,"星矢");t.setDaemon(true); t.start(); for (int i = 3; i >0; i-) System.out.println("我是雅典娜女神,我馬上死了!

12、"+i); if(i=1) System.out.println("我是雅典娜女神,我死了!");運(yùn)行結(jié)果如圖5-3所示。圖5-3 運(yùn)行結(jié)果三、案例總結(jié)1、在多線程程序中,一旦前臺(tái)線程(例如主線程)結(jié)束,后臺(tái)線程也就結(jié)束了。2、要將某個(gè)線程設(shè)置為后臺(tái)線程,該線程的setDaemon()方法必須在start()方法之前調(diào)用,否則會(huì)引發(fā)IllegalThreadStateException異常。案例5-4 線程的優(yōu)先級(jí)一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105007名 稱:線程的優(yōu)先級(jí)2、 練習(xí)目標(biāo)Ø 了解線程中優(yōu)先級(jí)的概念和作用Ø 掌握設(shè)置

13、線程優(yōu)先級(jí)的方法Ø 掌握線程設(shè)置優(yōu)先級(jí)方法中的三個(gè)靜態(tài)常量3、 需求分析在應(yīng)用程序中,如果要對(duì)線程進(jìn)行調(diào)度,最直接的方式就是設(shè)置線程的優(yōu)先級(jí)。這時(shí),可以通過(guò)線程的setPriority()方法來(lái)設(shè)置線程優(yōu)先級(jí)別,實(shí)現(xiàn)對(duì)線程的調(diào)度功能。為了讓初學(xué)者掌握線程的優(yōu)先級(jí),在案例中創(chuàng)建3個(gè)線程,分別為它們?cè)O(shè)置不同的優(yōu)先級(jí)來(lái)演示不同優(yōu)先級(jí)線程的調(diào)度。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Demo,使其實(shí)現(xiàn)Runnable接口。2) 在Demo類中重寫run()方法,在方法內(nèi)編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打?。壕€程名稱+循環(huán)次數(shù)。3) 編寫測(cè)試類Example04,在Example04類的ma

14、in()方法中,創(chuàng)建一個(gè)Demo對(duì)象,利用Thread的構(gòu)造方法創(chuàng)建三個(gè)線程對(duì)象并命名,使用setPriority()方法將其中兩個(gè)線程的優(yōu)先級(jí)設(shè)為最大和最小,最后開啟三個(gè)線程的start()方法。二、案例實(shí)現(xiàn)class Demo implements Runnable public void run() for (int x = 0; x < 5; x+) System.out.println(Thread.currentThread().getName() + "-" + x);public class Example04 public static void m

15、ain(String args) Demo d = new Demo();Thread t1 = new Thread(d,"楊過(guò)");Thread t2 = new Thread(d,"岳不群");Thread t3 = new Thread(d,"金龍");/設(shè)置線程的優(yōu)先級(jí)t3.setPriority(Thread.MAX_PRIORITY);t2.setPriority(1);t1.start();t2.start();t3.start();運(yùn)行結(jié)果如圖5-4所示。圖5-4 運(yùn)行結(jié)果三、案例總結(jié)1、在多線程程序中,可以通過(guò)設(shè)置

16、線程的優(yōu)先級(jí)別來(lái)控制線程獲得CPU執(zhí)行的幾率。2、線程的優(yōu)先級(jí)用110之間的整數(shù)來(lái)表示,數(shù)字越大優(yōu)先級(jí)越高。也可以使用靜態(tài)常量表示線程的優(yōu)先級(jí),如:MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY。3、雖然Java中提供了10個(gè)線程優(yōu)先級(jí),但是這些優(yōu)先級(jí)需要操作系統(tǒng)的支持,不同的操作系統(tǒng)對(duì)優(yōu)先級(jí)的支持是不一樣的,不能很好的和Java中線程優(yōu)先級(jí)一一對(duì)應(yīng),因此,在設(shè)計(jì)多線程應(yīng)用程序時(shí),其功能的實(shí)現(xiàn)一定不能依賴于線程的優(yōu)先級(jí),而只能把線程優(yōu)先級(jí)作為一種提高程序效率的手段。案例5-5 線程休眠一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105008名 稱:線程休眠2、 練

17、習(xí)目標(biāo)Ø 了解線程休眠的概念和作用Ø 掌握如何使用sleep(long millis)方法使線程休眠3、 需求分析如果希望人為地控制線程,使正在執(zhí)行的線程暫停,將CPU讓給別的線程。這時(shí),可以使用靜態(tài)方法sleep(long millis),該方法可以讓當(dāng)前正在執(zhí)行的線程暫停一段時(shí)間,進(jìn)入休眠等待狀態(tài)。為了讓初學(xué)者更好地掌握線程休眠,案例中將啟動(dòng)三個(gè)線程共同出售10張票來(lái)演示線程休眠及休眠引發(fā)的結(jié)果。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Ticket,使其實(shí)現(xiàn)Runnable接口,并在該類中創(chuàng)建int類型私有屬性tickets,賦初值為10。2) 在Ticket類中重

18、寫run()方法,在方法內(nèi)編寫一個(gè)while循環(huán)。循環(huán)體內(nèi)判斷ticket值,當(dāng)大于0時(shí),使用sleep(long millis)方法使線程休眠1秒鐘,并打?。寒?dāng)前線程名稱+“正在出售第”+循環(huán)次數(shù);否則結(jié)束循環(huán)。每執(zhí)行一次while循環(huán),tickets值減一。3) 編寫測(cè)試類Example05,在Example05類的main()方法中,創(chuàng)建一個(gè)Ticket對(duì)象,利用Thread的構(gòu)造方法創(chuàng)建三個(gè)線程對(duì)象并命名,并開啟三個(gè)線程的start()方法。二、案例實(shí)現(xiàn)class Ticket implements Runnable private int tickets = 10;public vo

19、id run() while (true) if (tickets > 0) try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace();System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets-) + "張票");public class Example05 public static void main(String args) Ticket tr = new Tick

20、et();Thread t1 = new Thread(tr);Thread t2 = new Thread(tr);Thread t3 = new Thread(tr);t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start(); 運(yùn)行結(jié)果如圖5-5所示。圖5-5 運(yùn)行結(jié)果從運(yùn)行結(jié)果可以看出,當(dāng)程序啟動(dòng)后,“窗口1”、“窗口2”、“窗口3”線程共同出售tikcets,但是最后“窗口1”出售了第0張票、“窗口3”出售了第-

21、1張票,從中可以推斷當(dāng)tickets=1時(shí),某一個(gè)線程進(jìn)入if分支語(yǔ)句后,線程休眠了1秒。在此期間,tickets的值依然為1,其他兩個(gè)線程也順利進(jìn)入了到if分支語(yǔ)句中,當(dāng)線程休眠時(shí)間結(jié)束后,三個(gè)線程分別操作了ticket值,所以造成了tickets值為負(fù)數(shù)。三、案例總結(jié)1、sleep(long millis)方法聲明拋出InterruptedException異常,因此在調(diào)用該方法時(shí)應(yīng)該捕獲異常,或者聲明拋出該異常。2、sleep()是靜態(tài)方法,只能控制當(dāng)前正在運(yùn)行的線程休眠,而不能控制其它線程休眠。當(dāng)休眠時(shí)間結(jié)束后,線程就會(huì)返回到就緒狀態(tài),而不是立即開始運(yùn)行。案例5-6 線程讓步一、案例描

22、述 1、 考核知識(shí)點(diǎn)編 號(hào):00105009名 稱:線程讓步2、 練習(xí)目標(biāo)Ø 了解線程讓步的概念和作用Ø 掌握設(shè)置線程讓步的方法3、 需求分析在校園中,我們經(jīng)常會(huì)看到同學(xué)互相搶籃球,當(dāng)某個(gè)同學(xué)搶到籃球后就可以拍一會(huì),之后他會(huì)把籃球讓出來(lái),大家重新開始搶籃球,這個(gè)過(guò)程就相當(dāng)于Java程序中的線程讓步。在多線程程序中,可以通過(guò)線程的yield()方法將線程轉(zhuǎn)換成就緒狀態(tài),讓系統(tǒng)的調(diào)度器重新調(diào)度一次,達(dá)到線程讓步的目的。案例中將在一個(gè)多線程程序中,通過(guò)yield()方法對(duì)其中一個(gè)線程設(shè)置線程讓步來(lái)演示。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Demo,使其實(shí)現(xiàn)Runnable

23、接口。2) 在Demo類中覆寫run()方法,在方法內(nèi)編寫一個(gè)for循環(huán),循環(huán)體內(nèi),先執(zhí)行線程讓步的方法yield(),然后輸出打印:線程名稱+循環(huán)次數(shù)。3) 編寫測(cè)試類Example06,在Example06類的main()方法中,創(chuàng)建一個(gè)Demo對(duì)象,利用Thread的構(gòu)造方法創(chuàng)建兩個(gè)線程對(duì)象,并執(zhí)行線程對(duì)象的start()方法,同時(shí)編寫for循環(huán),循環(huán)內(nèi)打印“main:”+當(dāng)前循環(huán)次數(shù)。二、案例實(shí)現(xiàn)class Demo implements Runnablepublic void run()for(int x = 0 ; x < 5 ; x+)Thread.yield();Syst

24、em.out.println(Thread.currentThread().getName()+"."+x);public class Example06 public static void main(String args)throws Exception Demo d = new Demo();Thread t0 = new Thread(d);Thread t1 = new Thread(d);t0.start();t1.start();for(int x = 0 ; x<5 ; x+)System.out.println("main."+

25、x);運(yùn)行結(jié)果如圖5-6所示。圖5-6 運(yùn)行結(jié)果三、案例總結(jié)1、在多線程程序中,可以通過(guò)設(shè)置線程讓步,讓系統(tǒng)的調(diào)度器重新調(diào)度一次CPU的分配。2、線程讓步和線程休眠是不一樣的,線程讓步不會(huì)阻塞該線程,它只是將線程轉(zhuǎn)換成就緒狀態(tài),而線程休眠,是讓線程在一定時(shí)間內(nèi)進(jìn)入休眠等待狀態(tài),到達(dá)時(shí)間后線程再轉(zhuǎn)換成就緒狀態(tài)。案例5-7 線程插隊(duì)一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105010名 稱:線程插隊(duì)2、 練習(xí)目標(biāo)Ø 了解線程插隊(duì)的概念和作用Ø 掌握線程插隊(duì)方法的使用3、 需求分析在火車站買票的時(shí)候,有的乘客著急趕火車,會(huì)插到隊(duì)伍前面先買車票,其他乘客再買票。那么在多線程程序中

26、,也可以通過(guò)線程插隊(duì),讓插隊(duì)的線程先執(zhí)行完,然后本線程才開始執(zhí)行。在案例中將通過(guò)使用join()方法來(lái)演示線程插隊(duì)。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Demo,使其實(shí)現(xiàn)Runnable接口。2) 在Demo類中覆寫run()方法,在方法內(nèi)編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打印:線程名稱+循環(huán)次數(shù)。3) 編寫測(cè)試類Example07,在Example07類的main()方法中,創(chuàng)建一個(gè)Demo對(duì)象,利用Thread的構(gòu)造方法創(chuàng)建兩個(gè)線程對(duì)象,分別命名“排隊(duì)隊(duì)員”和“插隊(duì)隊(duì)員”,然后編寫兩個(gè)線程對(duì)象的start()方法,然后調(diào)用“插隊(duì)隊(duì)員”線程的join()方法。二、案例實(shí)現(xiàn)class Dem

27、o implements Runnable public void run() for (int x = 0; x < 5; x+) System.out.println(Thread.currentThread().getName() + "-" + x); public class Example07 public static void main(String args) Demo jd = new Demo();Thread t1 = new Thread(jd);Thread t2 = new Thread(jd);t1.setName("排隊(duì)隊(duì)員

28、");t2.setName("插隊(duì)隊(duì)員");t1.start();t2.start();try t2.join(); catch (InterruptedException e) e.printStackTrace();運(yùn)行結(jié)果如圖5-7所示。 圖5-7 運(yùn)行結(jié)果三、案例總結(jié)1、線程插隊(duì),可以讓插隊(duì)的線程先執(zhí)行完,然后本線程才開始執(zhí)行。2、使用線程插隊(duì)join()方法時(shí),需要拋出InterruptedException異常。案例5-8 同步代碼塊的使用一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105012名 稱:同步代碼塊2、 練習(xí)目標(biāo)Ø 掌握同步代碼塊

29、作用Ø 掌握同步代碼塊的使用方法Ø 掌握同步代碼塊中鎖對(duì)象的使用3、 需求分析生活中,會(huì)遇到兩人上洗手間的問(wèn)題,甲使用洗手間的時(shí)候會(huì)鎖上門,乙看到門鎖上了,就需要等甲使用完后再使用的。那么在多線程程序中,可以通過(guò)將共享資源放在同步代碼塊內(nèi)來(lái)實(shí)現(xiàn)多個(gè)線程同步處理共享資源的問(wèn)題。本案例將通過(guò)兩個(gè)線程共享資源來(lái)演示同步代碼塊的使用。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類Demo,使其實(shí)現(xiàn)Runnable接口。2) 在Demo類中覆寫run()方法,在方法內(nèi)編寫synchronized同步代碼塊,在進(jìn)入同步代碼塊時(shí),打印線程名稱,然后編寫一個(gè)for循環(huán),循環(huán)體內(nèi)打印:運(yùn)行線程

30、名稱+循環(huán)次數(shù)。當(dāng)循環(huán)次數(shù)等于3時(shí),跳出循環(huán)。3) 編寫測(cè)試類Example08,在Example08類的main()方法中,創(chuàng)建一個(gè)Demo對(duì)象,利用Thread的構(gòu)造方法創(chuàng)建兩個(gè)線程對(duì)象,分別命名“張三”和“李四”,執(zhí)行兩個(gè)線程的start()方法。二、案例實(shí)現(xiàn)class Demo implements Runnable private Object obj = new Object();public void run() synchronized (obj) System.out.println(Thread.currentThread().getName()+ "進(jìn)入洗手間,

31、門以鎖上");for (int i = 1; i < 10; i+) System.out.println(Thread.currentThread().getName()+ "正在使用洗手間"+i);if (i = 3) System.out.println(Thread.currentThread().getName()+ "用完,準(zhǔn)備出去,鎖打開");break;public class Example08 public static void main(String args) Demo d = new Demo();Thread

32、 t1 = new Thread(d, "張三");Thread t2 = new Thread(d, "李四");t1.start();t2.start();運(yùn)行結(jié)果如圖5-8所示。圖5-8 運(yùn)行結(jié)果三、案例總結(jié)1、同步代碼塊中的鎖對(duì)象可以是任意類型的對(duì)象,但多個(gè)線程共享的鎖對(duì)象必須是唯一的。2、鎖對(duì)象的創(chuàng)建代碼不能放到run()方法中,否則每個(gè)線程運(yùn)行到run()方法都會(huì)創(chuàng)建一個(gè)新對(duì)象,這樣每個(gè)線程都會(huì)有一個(gè)不同的鎖,每個(gè)鎖都有自己的標(biāo)志位。線程之間便不能產(chǎn)生同步的效果。案例5-9 同步代碼塊嵌套造成死鎖一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):0010

33、5014名 稱:死鎖2、 練習(xí)目標(biāo)Ø 了解什么是死鎖和造成死鎖的原因3、 需求分析在編寫多線程程序中,經(jīng)常出現(xiàn)多個(gè)同步代碼塊嵌套的情況,而此時(shí)如果沒(méi)有控制好鎖對(duì)象的一致性就會(huì)出現(xiàn)死鎖現(xiàn)象,接下來(lái),在案例中通過(guò)同步代碼塊之間的互相嵌套來(lái)演示線程死鎖。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 自定義一個(gè)類DieLock,使其繼承Thread。2) 在DieLock類中創(chuàng)建兩個(gè)靜態(tài)常量objA、objB,分別是a鎖、b鎖。然后創(chuàng)建一個(gè)boolean類型的私有屬性flag作為標(biāo)示符,并編寫DieLock的構(gòu)造方法3) 重寫run()方法,在方法內(nèi)首先判斷flag的值。當(dāng)flag值為true時(shí),分別以o

34、bjA和objB 為鎖對(duì)象,編寫兩個(gè)嵌套的同步代碼塊,并在同步代碼塊中打印flag值和鎖對(duì)象名稱;當(dāng)flag為值為false時(shí),編寫flag為false時(shí)的代碼,只是把鎖對(duì)象的順序更換一下。4) 編寫測(cè)試類Example09,在Example09類的main()方法中,利用DieLock的構(gòu)造方法,創(chuàng)建兩個(gè)DieLock對(duì)象,傳入的flag值分別為true和false,執(zhí)行兩個(gè)線程的start()方法。二、案例實(shí)現(xiàn)class DieLock extends Thread private boolean flag;static Object objA = new Object();static

35、Object objB = new Object();public DieLock(boolean flag) this.flag = flag;public void run() if (flag) synchronized (objA) System.out.println("true - objA");synchronized (objB) System.out.println("true - objB"); else synchronized (objB) System.out.println("false - objB");

36、synchronized (objA) System.out.println("false - objA"); public class Example09 public static void main(String args) new DieLock(true).start();new DieLock(false).start();運(yùn)行結(jié)果如圖5-9所示。圖5-9 運(yùn)行結(jié)果三、案例總結(jié)當(dāng)兩個(gè)線程的同步代碼塊彼此拿著對(duì)方需要的鎖時(shí),程序不會(huì)停止,但會(huì)一直“卡頓”,這種現(xiàn)象就是“死鎖”現(xiàn)象。案例5-10 多線程通信一、案例描述 1、 考核知識(shí)點(diǎn)編 號(hào):00105015名 稱

37、:多線程通信2、 練習(xí)目標(biāo)Ø 掌握如何解決線程通信中的共享資源的安全問(wèn)題3、 需求分析一條生產(chǎn)線的上下兩個(gè)工序,它們必須以規(guī)定的速率完成各自的工作,才能保證產(chǎn)品在流水線中順利的流轉(zhuǎn)。在多線程的程序中,上下工序可以看作兩個(gè)線程,這兩個(gè)線程之間需要協(xié)同完成工作,就需要線程之間進(jìn)行通信。了讓初學(xué)者掌握多線程通信,案例中將通過(guò)生產(chǎn)和消費(fèi)鼠標(biāo)這兩個(gè)過(guò)程的多線程協(xié)調(diào)來(lái)演示。4、 設(shè)計(jì)思路(實(shí)現(xiàn)原理)1) 創(chuàng)建一個(gè)產(chǎn)品類Product,該類有三個(gè)屬性分別是:產(chǎn)品名稱name,產(chǎn)品數(shù)量count,和一個(gè)boolean類型的標(biāo)示量flag。當(dāng)flag值為false時(shí),說(shuō)明產(chǎn)品未生產(chǎn),當(dāng)flag值為tr

38、ue時(shí),說(shuō)明產(chǎn)品已生產(chǎn)。2) 在Product類中編寫一個(gè)同步方法set(),每次調(diào)用set()方法時(shí),表示要生成一個(gè)產(chǎn)品。在set()方法中,編寫一個(gè)while循環(huán),當(dāng)flag值為true時(shí),調(diào)用該線程的wait()方法,讓線程等待。在while循環(huán)體外,count值遞增,并打印當(dāng)前線程名稱和產(chǎn)品名稱及數(shù)量,最后將flag值設(shè)為true,并喚醒所有的線程。3) 在Product類中編寫一個(gè)同步方法get(),每次調(diào)用get()方法時(shí),表示要消費(fèi)一件產(chǎn)品。在get()方法中,編寫一個(gè)while循環(huán),當(dāng)flag值為false時(shí),調(diào)用該線程的wait()方法,讓線程等待。在循環(huán)體外,打印當(dāng)前線程名

39、稱和被消費(fèi)的產(chǎn)品名稱和個(gè)數(shù)。最后將flag值設(shè)為false,并喚醒所有的線程。4) 編寫一個(gè)生產(chǎn)類Producter,該類定義了一個(gè)Product類型的成員變量和有參構(gòu)造方法,構(gòu)造方法中的參數(shù)用于為Product對(duì)象賦值,并且Producter類實(shí)現(xiàn)了Runnable接口。5) 重寫Runnbale接口的run()方法,在run()方法內(nèi),執(zhí)行死循環(huán),每循環(huán)一次調(diào)用Product對(duì)象的set()方法。6) 編寫一個(gè)消費(fèi)類Customer,該類定義了一個(gè)Product類型的成員變量和有參構(gòu)造方法,構(gòu)造方法中的參數(shù)用于為Product對(duì)象賦值,并且Customer類實(shí)現(xiàn)了Runnable接口。7) 重寫Runnable接口的run()方法,在run()方法內(nèi),執(zhí)行死循環(huán),每循環(huán)一次就調(diào)用producet對(duì)象的get()方法。8) 編寫一個(gè)測(cè)試類Example10,創(chuàng)建一個(gè)Product對(duì)象,生產(chǎn)者和消費(fèi)者分別利用product對(duì)象創(chuàng)建各自的對(duì)象,最后使用Thread類創(chuàng)建2個(gè)“生產(chǎn)者”線程和2個(gè)“消費(fèi)者”線程,并執(zhí)行四個(gè)線程的start()方法。二、案例實(shí)現(xiàn)/定義產(chǎn)品類class Product private int coun

溫馨提示

  • 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)論