第七章JAVA多線程與異常處理_第1頁
第七章JAVA多線程與異常處理_第2頁
第七章JAVA多線程與異常處理_第3頁
第七章JAVA多線程與異常處理_第4頁
第七章JAVA多線程與異常處理_第5頁
已閱讀5頁,還剩73頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、Java語言程序設計語言程序設計(第第2版版)第第7章章 多線程與異常處理多線程與異常處理Java語言程序設計語言程序設計(第第2版版)本章主要內(nèi)容:7.1 異常處理7.1.1 Java的異常處理機制7.1.2異常的拋出7.1.3異常處理7.2 多線程的基本概念7.2.1 線程與多線程7.2.2 線程的生命周期7.2.3 線程的優(yōu)先級Java語言程序設計語言程序設計(第第2版版)7.3 線程的使用方法7.3.1創(chuàng)建Thread子類構造線程7.3.2 實現(xiàn)Runnable接口構造線程7.4 線程同步7.4.1使用多線程造成的數(shù)據(jù)混亂7.4.2 同步線程Java語言程序設計語言程序設計(第第2版版

2、)Java的基本理念是“結構不佳的代碼將不能運行”。編譯期的錯誤會由編譯器偵測到執(zhí)行期的錯誤會引發(fā)異常Java語言程序設計語言程序設計(第第2版版)7.1 異常處理異常處理異常(異常(Exception)指程序)指程序運運行行過程中出現(xiàn)的非正?,F(xiàn)象,過程中出現(xiàn)的非正?,F(xiàn)象,例如用戶輸入錯誤、需要處理例如用戶輸入錯誤、需要處理的文件不存在、在網(wǎng)絡上傳輸?shù)奈募淮嬖?、在網(wǎng)絡上傳輸數(shù)據(jù)但網(wǎng)絡沒有連接等。數(shù)據(jù)但網(wǎng)絡沒有連接等。 Java語言程序設計語言程序設計(第第2版版)7.1.1 Java的異常處理機制的異常處理機制在在Java中,把異常分為錯誤(中,把異常分為錯誤(Error)與)與異常(異常(

3、Exception)兩大類。(如下頁)兩大類。(如下頁所示)所示) Exception類有自己的方法和屬性。它類有自己的方法和屬性。它的構造方法有兩個:的構造方法有兩個: public Exception ( ); public Exception (String s);Java語言程序設計語言程序設計(第第2版版)Object Throwable Error VirtualMachineError AWTError Exception RuntimeException ArithmeticException IndexOutOfBoundsException IOException File

4、NotFoundExceptionJava語言程序設計語言程序設計(第第2版版)7.1.1 Java的異常處理機制的異常處理機制 系統(tǒng)定義的運行異常系統(tǒng)定義的運行異常 系統(tǒng)定義的運行異常說明ClassNotFoundException 找不到要裝載的類,由Class.forName拋出ArrayIndexOutOfBoundsException 數(shù)組下標出界FileNotFoundException找不到指定的文件或目錄IOException輸入輸出錯誤NullPointerException 非法使用空引用ArithmeticException算術錯誤,如除數(shù)為0InterruptedExc

5、eption一個線程被另一個線程中斷UnknownHostException無法確定主機的IP地址SecurityException 安全性錯誤MalfomedURLException URL格式錯誤Java語言程序設計語言程序設計(第第2版版)7.1.2異常的拋出異常的拋出1、系統(tǒng)自動拋出的異常、系統(tǒng)自動拋出的異?!纠?-1】創(chuàng)建一個有錯誤的程序,測試異常拋出的情況。創(chuàng)建一個有錯誤的程序,測試異常拋出的情況。1. /* 測試除數(shù)為測試除數(shù)為0時拋出的異常時拋出的異常 */2.class Example7_13.4. public static void main(String args)

6、5. 6. int a=5,d=0;7.System.out.println(a/d);8. 9.Java語言程序設計語言程序設計(第第2版版)7.1.3異常處理異常處理異常處理的方法有二種:一種方法是使用trycatchfinally結構對異常進行捕獲和處理;另一種方法是通過throws和throw拋出異常。下面重點介紹使用trycatchfinally結構對異常進行捕獲和處理。 Java語言程序設計語言程序設計(第第2版版)trycatchfinally結構對異常進行捕獲和處理的形式結構對異常進行捕獲和處理的形式: try 可能出現(xiàn)異常的程序代碼可能出現(xiàn)異常的程序代碼 catch(異常類異

7、常類1變量變量1) 異常類異常類1對應的異常處理代碼對應的異常處理代碼catch(異常類異常類2變量變量2) 異常類異常類2對應的異常處理代碼對應的異常處理代碼 .finally 無論異常是否發(fā)生都要執(zhí)行的代碼無論異常是否發(fā)生都要執(zhí)行的代碼 Java語言程序設計語言程序設計(第第2版版)【例例7-27-2】應用異常處理修改例應用異常處理修改例7-17-1。class Example7_2 public static void main(String args) int a=5,b=0;try System.out.println(a/b); catch(Exception e) System.

8、out.println(“除數(shù)為除數(shù)為0); Java語言程序設計語言程序設計(第第2版版)【例例7-3】數(shù)組下標越界引發(fā)異常數(shù)組下標越界引發(fā)異常 class Example7_3 public static void main(String args) int a=1,2,3,4,5; int sum=0; try for (int i=0;i=5 ;i+ ) sum+=ai; System.out.println(sum=+sum); catch(ArrayIndexOutOfBoundsException e) System.out.println(發(fā)生異常原因:+e); finally

9、 System.out.println(程序運行結束!); Java語言程序設計語言程序設計(第第2版版)創(chuàng)建自己的異常(1)類名稱: 用于標識異常的類型要自己定義異常類,一定要繼承某個既有的異常型別class MyException extends Exception ExceptionMyExceptionThrowableJava語言程序設計語言程序設計(第第2版版)/: c09:SimpleExceptionDemo.javaclass SimpleException extends Exception public class SimpleExceptionDemo public v

10、oid f( ) throws SimpleException System.out.println(Throw SimpleException from f(); throw new SimpleException(); / 若一個方法不能處理所引發(fā)的異常,異常處理交調(diào)用者/ 完成,在方法的定義中要有 throws/ 若丟出的異常不是 Error 或 RuntimeExcption 及其子類/ 的對象,就必須加 throws 子句Java語言程序設計語言程序設計(第第2版版)public static void main(String args) SimpleExceptionDemo se

11、d = new SimpleExceptionDemo(); try sed.f(); catch(SimpleException e) System.err.println(Caught it!); /:輸出結果:Throw SimpleException from f()Caught it!lSystem.err: 輸出錯誤信息; 優(yōu)于System.outl因為把結果送到System.err,它不會隨System.out一起被重定向Java語言程序設計語言程序設計(第第2版版)異常的方法:從基類從基類Throwable繼承的方法繼承的方法String getMessage( ):取得細節(jié)消

12、息String getLocalizedMessage: 取得細節(jié)消息(特定語系)String toString: 返回 Throwable 的簡短描述(詳細的消息,如果有的話)void printStackTrace (.):打印出Throwable 和 Throwable 的調(diào)用堆棧路徑 上述函數(shù)依序提供更詳細信息Throwable fillStackTrace ( ):把 Stack 狀態(tài)記錄于 Throwable ,用于重擲Java語言程序設計語言程序設計(第第2版版)/: c09:ExceptionMethods.java / Demonstrating the Exception

13、Methods.public class ExceptionMethods public static void main(String args) try throw new Exception(Heress my Exception); catch(Exception e) System.err.println(Caught Exception); System.err.println(e.getMessage(): + e.getMessage(); System.err.println(e.getLocalizedMessage(): + e.getLocalizedMessage()

14、; System.err.println(e.toString(): + e); System.err.println(e.printStackTrace():); e.printStackTrace( System.err); /:異常的方法異常的方法: 舉例舉例Java語言程序設計語言程序設計(第第2版版)輸出結果:Caught Exceptione.getMessage():Heres my Exceptione.getLocalizedMessage():Heres my Exceptione.toString():java.lang.Exception: Heres my Excep

15、tione.printStackTrace():java.lang.Exception: Heres my Exceptionat ExceptionMethods.main(ExceptionMethods.java:6)l每個方法都比前一個提供了更多的信息-實際上它們每一個都是前一個的超集。Java語言程序設計語言程序設計(第第2版版)重擲異常(或重新拋出異常)想重新擲出剛才捕捉過的異常,特別是在運用Exception捕獲所有可能的異常時,用 throw 關鍵字將同一個異常重新擲出。由于已獲得當前異常的reference,所以只需簡單地重新擲出那個reference即可。下面是一個例子:J

16、ava語言程序設計語言程序設計(第第2版版)catch(Exception e) System.out.println(“一個異常已經(jīng)產(chǎn)生”); throw e;重擲一個異常導致異常進入更高一級環(huán)境的異??刂破髦小M粋€try塊的后續(xù)catch子句將被忽略。此外,與異常對象有關的所有東西都會得到保留。Java語言程序設計語言程序設計(第第2版版)重擲一個異常void f() try f1(); catch (Type1 e) / Exception handler void f1() try f2(); catch (Type1 e) throw e; void f2() throw new

17、Type1();1234Java語言程序設計語言程序設計(第第2版版)Java標準異常Throwable這個Java類被用來表示任何可以作為異常 被拋出的類。Throwable對象可分為兩種類型 Error :用來表示你不用關心的編譯期和系統(tǒng)錯誤 Exception:是可以被拋出的基本類型ThrowableErrorExceptionl異常的基本的概念是用名稱代表發(fā)生的問題,并且異常的名稱應該可以望文知意。Java語言程序設計語言程序設計(第第2版版)運行期異常(運行期異常(RuntimeException)的特例:)的特例:對于RuntimeException,通常不需要我們?nèi)ゲ东@,這類異常

18、由Java運行系統(tǒng)自動拋出并自動處理。對于對象引用t,傳給你的時候可能尚未被初始化。所以在使用這個引用調(diào)用其方法之前,你會先對引用進行檢查。if(t = null) throw new NullPointerException(); 如果在null引用上調(diào)用方法,Java會自動拋出NullPointerException異常。所以上述代碼是多余的。屬于運行期異常的類型有很多。這些異常都是從RuntimeException類繼承而來,這種異常屬于錯誤,將被自動捕獲。Java語言程序設計語言程序設計(第第2版版)請務必記住:你只能在代碼中忽略RuntimeException(及其子類)類型的異常,

19、其它類型異常的處理都是由編譯器強制實施的。RuntimeException代表的是編程錯誤: 1你無法預料的錯誤。比如從你控制范圍之外傳遞進來的null引用。2作為程序員,你應該在代碼中進行檢查的錯誤。(比如對于ArrayIndexOutOfBoundsException,你就得注意一下數(shù)組的大小了。)在一個地方發(fā)生的異常,常常會在另一個地方導致錯誤。Java語言程序設計語言程序設計(第第2版版)異常對比異常處理系統(tǒng)會按處理函數(shù)的順序搜索“最接近”的處理程序。一旦找到,就認為異常已得到控制,不再進行更多的搜索工作catch 順序不對,編譯會報錯在安排catch語句的順序時,首先應該捕獲最特殊的

20、異常,然后再逐漸一般化。也就是捕獲子類異常的catch語句在前,捕獲超類異常的catch語句在后。Java語言程序設計語言程序設計(第第2版版)/: c10:Human.java/ Catching exception hierarchies.class Annoyance extends Exception class Sneeze extends Annoyance public class Human public static void main(String args) try throw new Sneeze(); catch(Sneeze s) System.err.printl

21、n(Caught Sneeze); catch(Annoyance a) System.err.println(Caught Annoyance); /:Java語言程序設計語言程序設計(第第2版版)輸出結果:Caugh Sneeze注:先父類后子類編譯會報錯 只有父類沒有子類 OK try throw new Sneeze(); catch(Annoyance a) /父類 System.err.println(Caught Annoyance ); catch(Sneeze s ) /子類 System.err.println(Caught Sneeze s ); Java語言程序設計語言

22、程序設計(第第2版版)7.2 多線程的基本概念多線程的基本概念什么是線程什么是線程7.2.1 線程與多線程線程與多線程Java語言程序設計語言程序設計(第第2版版)7.2.1 線程與多線程線程與多線程進程與多線程的區(qū)別進程與多線程的區(qū)別Java語言程序設計語言程序設計(第第2版版)Java的多線程機制的多線程機制在在Java編程中,每實例化一個線程對象,就創(chuàng)建編程中,每實例化一個線程對象,就創(chuàng)建一個虛擬的一個虛擬的CPU,由虛擬,由虛擬CPU處理本線程數(shù)據(jù)。處理本線程數(shù)據(jù)。每個每個Java程序都有一個主線程,即由程序都有一個主線程,即由main()方法方法所對應的線程。對于所對應的線程。對于a

23、pplet,瀏覽器即是主線程。,瀏覽器即是主線程。除主線程外,線程無法自行啟動,必須通過其他除主線程外,線程無法自行啟動,必須通過其他程序來啟動它。程序來啟動它。7.2.1 線程與多線程線程與多線程Java語言程序設計語言程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期線程要經(jīng)歷創(chuàng)建、線程要經(jīng)歷創(chuàng)建、就緒、運行、阻就緒、運行、阻塞和死亡等塞和死亡等5個狀個狀態(tài)態(tài) ,稱為生命周,稱為生命周期。期。Java語言程序設計語言程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期1、創(chuàng)建狀態(tài)創(chuàng)建狀態(tài)當我們通過new命令創(chuàng)建了一個線程對象,則該線程對象就處于創(chuàng)建狀態(tài)。如下面語句所示

24、: Thread thread1 = new Thread();創(chuàng)建狀態(tài)是線程已被創(chuàng)建但未開始執(zhí)行的一個特殊狀態(tài)。此時線程對象擁有自己的內(nèi)存空間,但沒有分配CPU資源,需通過start()方法調(diào)度進入就緒狀態(tài)等待CPU資源。Java語言程序設計語言程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期2、就緒狀態(tài)、就緒狀態(tài)處于創(chuàng)建狀態(tài)的線程對象通過處于創(chuàng)建狀態(tài)的線程對象通過start()方法進入就緒方法進入就緒狀態(tài),如下面語句所示:狀態(tài),如下面語句所示:Thread thread1 = new Thread();Thread1.start();start()方法同時調(diào)用了線程體,也就是

25、方法同時調(diào)用了線程體,也就是run()方法,方法,表示線程對象正等待表示線程對象正等待CPU資源,隨時可被調(diào)用執(zhí)行。資源,隨時可被調(diào)用執(zhí)行。Java語言程序設計語言程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期3、運行狀態(tài)、運行狀態(tài)若線程處于正在運行的狀態(tài),表示線程已經(jīng)擁有了若線程處于正在運行的狀態(tài),表示線程已經(jīng)擁有了對處理器的控制權,其代碼目前正在運行,除非運對處理器的控制權,其代碼目前正在運行,除非運行過程中控制權被另一優(yōu)先級更高的線程搶占,否行過程中控制權被另一優(yōu)先級更高的線程搶占,否則這一線程將一直持續(xù)到運行完畢。則這一線程將一直持續(xù)到運行完畢。Java語言程序設計語言

26、程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期4、阻塞狀態(tài)、阻塞狀態(tài)如果一個線程處于阻塞狀態(tài),那么該線程則無法如果一個線程處于阻塞狀態(tài),那么該線程則無法進入就緒隊列。處于阻塞狀態(tài)的線程通常必須由進入就緒隊列。處于阻塞狀態(tài)的線程通常必須由某些事件喚醒。某些事件喚醒。 5、死亡狀態(tài)、死亡狀態(tài)死亡狀態(tài)(或終止狀態(tài)),表示線程已退出運行死亡狀態(tài)(或終止狀態(tài)),表示線程已退出運行狀態(tài),并且不再進入就緒隊列。狀態(tài),并且不再進入就緒隊列。 Java語言程序設計語言程序設計(第第2版版)7.2.2 線程的生命周期線程的生命周期簡單歸納一下,一個線程的生命周期一般經(jīng)過如下步驟:(1)一個線程通過

27、new()操作實例化后,進入新生狀態(tài)。(2)通過調(diào)用start()方法進入就緒狀態(tài),一個處在就緒狀態(tài)的線程將被調(diào)度執(zhí)行,執(zhí)行該線程相應的run()方法中的代碼。(3)通過調(diào)用線程的(或從Object類繼承過來的)sleep()或wait()方法,這個線程進入阻塞狀態(tài)。一個線程也可能自己完成阻塞操作。(4)當run()方法執(zhí)行完畢,或者有一個例外產(chǎn)生,或者執(zhí)行System.exit()方法,則一個線程就進入死亡狀態(tài)。 Java語言程序設計語言程序設計(第第2版版)7.3 線程的使用方法線程的使用方法在Java語言中,可采用兩種方式產(chǎn)生線程:(1)通過創(chuàng)建Thread類的子類來構造線程。Java定

28、義了一個直接從根類Object中派生的Thread類。所有從這個類派生的子類或間接子類,均為線程。(2)通過實現(xiàn)一個Runnable接口的類來構造線程。Java語言程序設計語言程序設計(第第2版版)7.3.1創(chuàng)建創(chuàng)建Thread子類構造線程子類構造線程 我們可以通過繼承Thread類,建立一個Thread類的子類并重新設計(重載)其run()方法來構造線程。 線程的創(chuàng)建與啟動線程的創(chuàng)建與啟動(1)創(chuàng)建一個)創(chuàng)建一個Thread類的子類;類的子類;(2)在子類中重新定義自己的)在子類中重新定義自己的run()方法,這個中包含方法,這個中包含了線程要實現(xiàn)的操作;了線程要實現(xiàn)的操作;(3)用關鍵字)

29、用關鍵字new 創(chuàng)建一個線程對象;創(chuàng)建一個線程對象;(4)調(diào)用)調(diào)用start()方法啟動線程。方法啟動線程。Java語言程序設計語言程序設計(第第2版版)【例例7-47-4】創(chuàng)建二個創(chuàng)建二個ThreadThread類的子類,類的子類,然后在另一個類中然后在另一個類中建立這建立這2 2個個ThreadThread類類的對象來測試它,的對象來測試它,看具體會發(fā)生什么看具體會發(fā)生什么現(xiàn)象。現(xiàn)象。Java語言程序設計語言程序設計(第第2版版)這個例子說明了這樣幾個事實:(1)創(chuàng)建獨立執(zhí)行線程比較容易,Java負責處理了大部分細節(jié)。(2)各線程并發(fā)運行,共同爭搶CPU資源,線程搶奪到CPU資源后,就開

30、始執(zhí)行,無法準確知道某線程能在什么時候開始執(zhí)行。(3)線程間的執(zhí)行是相互獨立的。(4)線程獨立于啟動它的線程(或程序)。Java語言程序設計語言程序設計(第第2版版)線程的暫停和恢復線程的暫停和恢復(1)sleep()方法該方法指定線程休眠一段時間。如下面語句所示:Thread thread1 = new Thread();thread1.start();try thread1.sleep(2000); catch(InterruptedException e) (2)yield()方法(3)wait()和notify()方法Java語言程序設計語言程序設計(第第2版版)7.3.2 實現(xiàn)實現(xiàn)R

31、unnable接口構造線程接口構造線程 1、實現(xiàn)、實現(xiàn)Runnable接口接口2、定義、定義run( )方法方法3、構造線程:、構造線程:Thread(Runnable對象名對象名);4、啟動線程:線程對象、啟動線程:線程對象.start( );Java語言程序設計語言程序設計(第第2版版)【例7-5】創(chuàng)建一個實現(xiàn)Runnable接口的線程類,然后在另一個類中建立2個線程對象來測試它,看具體會發(fā)生什么現(xiàn)象。Java語言程序設計語言程序設計(第第2版版)【例例7-6】 我們用我們用Thread子類程序來子類程序來模擬航班售票系統(tǒng),模擬航班售票系統(tǒng),實現(xiàn)四個售票窗口實現(xiàn)四個售票窗口發(fā)售某班次航班的

32、發(fā)售某班次航班的100張機票,一個售張機票,一個售票窗口用一個線程票窗口用一個線程來表示。來表示。Java語言程序設計語言程序設計(第第2版版)【例例7-7】 用用Runnable接口程序來接口程序來模擬航班售票系統(tǒng),模擬航班售票系統(tǒng),實現(xiàn)四個售票窗口發(fā)實現(xiàn)四個售票窗口發(fā)售某班次航班的售某班次航班的100張張機票,一個售票窗口機票,一個售票窗口用一個線程來表示。用一個線程來表示。Java語言程序設計語言程序設計(第第2版版)【例例7-8】 設計一個多線程的應用程序,模設計一個多線程的應用程序,模擬一個臺子上有多個彈子在上面滾動。擬一個臺子上有多個彈子在上面滾動。“彈子彈子”在碰到在碰到“臺子臺

33、子”的邊緣時會被彈的邊緣時會被彈回來。回來。 Java語言程序設計語言程序設計(第第2版版)7.4 線程同步線程同步由于多線程要共享內(nèi)存資源,因此有可能一個線程正在使用某個資源,而另一個線程卻在更新它,這樣,會造成數(shù)據(jù)的不正確。因此對于多個線程共享的資源,必須采取措施,使得每次只有一個線程能使用它,這就是多線程中的同步(synchronization)問題。 Java語言程序設計語言程序設計(第第2版版)7.4.1使用多線程造成的數(shù)據(jù)混亂使用多線程造成的數(shù)據(jù)混亂【例7-9】 設計一個模擬用戶從銀行取款的應用程序。設某銀行帳戶存款額的初值是2000元,用線程模擬兩個用戶從銀行取款的情況。 通過對

34、該程序的分析,發(fā)現(xiàn)出現(xiàn)錯誤結果的根本原因是兩個并發(fā)線程共享同一內(nèi)存變量所引起的。后一線程對變量的更改結果覆蓋了前一線程對變量的更改結果,造成數(shù)據(jù)混亂。 Java語言程序設計語言程序設計(第第2版版)7.4.2 同步線程同步線程1、Synchronized方法方法Java語言程序設計語言程序設計(第第2版版) 聲明Synchronized方法的一般格式為: public synchronized 返回類型 方法名() /* 方法體 */ Java語言程序設計語言程序設計(第第2版版)【例例7-107-10】 改寫例改寫例7-97-9,用線程同步的方法設計,用線程同步的方法設計用戶從銀行取款的應用

35、程序。用戶從銀行取款的應用程序。Java語言程序設計語言程序設計(第第2版版)線程間的通信經(jīng)典的隊列問題,一個線程產(chǎn)生一些數(shù)據(jù),而另一些線程取走數(shù)據(jù)。假設生產(chǎn)者生產(chǎn)更多的數(shù)據(jù)之前必須等到消費者結束。Java通過wait( )、notify( )和notifyAll( )方法實現(xiàn)了一個巧妙的進程內(nèi)通信的機制。這些方法作為Object的final方法來實現(xiàn)。這三個方法只可以在一個同步的上下文訪問。Java語言程序設計語言程序設計(第第2版版)wait( ):告訴調(diào)用線程放棄監(jiān)控器并進入睡眠狀態(tài),直到其他線程進入同一監(jiān)控器并調(diào)用notify( )方法。notify( ):喚醒第一個等待同一對象的線程

36、。notifyAll( ):喚醒所有對同一對象調(diào)用的線程,并且最高優(yōu)先級的線程先運行。Java語言程序設計語言程序設計(第第2版版)我們經(jīng)常在電視上看到,一個偵查員獲取情報后,將情報放到一個隱蔽的樹洞中,并且通知另外一個人來取走情報,自己等待,當取情報的人接到通知后,會從樹洞中取走情報,并且通知偵查員繼續(xù)放情報,它自己等待。當偵查員接到取走情報的通知后,它就繼續(xù)往樹洞中放情報。并且通知取情報的人來取情報。Java語言程序設計語言程序設計(第第2版版)分析一下剛才的場景:偵查員-生產(chǎn)者 獲取情報的人-消費者分析一下有幾個對象:1.偵查員是一個對象 2.獲取情報的人是一個對象3.樹洞是一個對象,用

37、來存放數(shù)據(jù)。以面向?qū)ο蟮乃枷?,應該將?shù)據(jù)和相應的方法組織在一起:樹洞這個類提供得到數(shù)據(jù)和取走數(shù)據(jù)的方法。Java語言程序設計語言程序設計(第第2版版)2、管程及、管程及wait()、notify()方法方法【例例7-11】設計一個模擬車輛通過交通路設計一個模擬車輛通過交通路口的程序??诘某绦?。 本示例創(chuàng)建了三個類,一個是本示例創(chuàng)建了三個類,一個是車輛類車輛類ICar,由線程繪制,由線程繪制2輛不輛不同方向行駛的小車。同方向行駛的小車。 另一個是交通警察類另一個是交通警察類TrafficCop,控制二輛車的線,控制二輛車的線程同步,程同步,(根據(jù)車輛的位置根據(jù)車輛的位置)。 還有一個是車輛在道路

38、上行駛還有一個是車輛在道路上行駛的窗體類的窗體類Car,該類繪制了,該類繪制了2條條相互垂直的道路,調(diào)用車輛線相互垂直的道路,調(diào)用車輛線程程(車輛行駛車輛行駛)。Java語言程序設計語言程序設計(第第2版版)死鎖因為線程可以阻塞,并且對象可以具有同步控制方法,用以防止別的線程在鎖還沒有釋放的時候就訪問這個對象。所以就可能出現(xiàn)這種情況:某個線程在等待另一個線程,而后者又等待別的線程,這樣一直下去,直到這個鏈條上的線程又在等待第一個線程釋放鎖。你將得到一個線程之間相互等待的連續(xù)循環(huán),沒有哪個線程能繼續(xù)。這被稱之為“死鎖”(deadlock)。Java語言程序設計語言程序設計(第第2版版)如果你運行

39、一個程序,而它馬上就死鎖了,你當時就能知道出了問題,并且可以跟蹤下去。真正的問題在于,你的程序可能看起來工作良好,但是具有潛在的死鎖危險。這時,死鎖可能發(fā)生,而事先卻沒有任何征兆,所以它會潛伏在你的程序里,直到客戶發(fā)現(xiàn)它出乎意料地發(fā)生。因此,在編寫并發(fā)程序的時候,進行仔細的程序設計以防止死鎖是一個關鍵部分。Java語言程序設計語言程序設計(第第2版版)讓我們看一下經(jīng)典的死鎖現(xiàn)象,它是由Dijkstra提出的:哲學家就餐問題。其內(nèi)容是指定五個哲學家。這些哲學家將用部分的時間思考,部分的時間就餐。當他們思考的時候,不需要任何共享資源,但當他們就餐的時候,他們坐在桌子旁并且只有有限數(shù)量的餐具。在問題

40、的原始描述中,餐具是叉子,要吃到桌子中央盤子里的意大利面條需要用兩把叉子,不過把餐具看成是筷子更合理;很明顯,哲學家要就餐就需要兩根筷子。Java語言程序設計語言程序設計(第第2版版)問題中引入的難點是:作為哲學家,他們很窮,所以他們只能買的起五根筷子。他們圍坐在桌子周圍,每人之間放一根筷子。當一個哲學家要就餐的時候,他/她必須同時得到左邊和右邊的筷子。如果一個哲學家左邊或右邊已經(jīng)有人在使用筷子了,那么這個哲學家就必須等待。Java語言程序設計語言程序設計(第第2版版)注意,這個問題之所以有趣,其原因是它顯示了一個程序可能看起來運行正確,但確實存在死鎖的危險。要演示這一點,命令行參數(shù)允許你調(diào)整

41、哲學家的數(shù)量以及一個影響哲學家思考時間的因子。如果你有許多哲學家,并且/或者他們花很多時間去思考,那么盡管存在死鎖可能,你可能永遠也看不到死鎖。默認的命令行參數(shù)是傾向于使死鎖盡快發(fā)生:Java語言程序設計語言程序設計(第第2版版)Java語言程序設計語言程序設計(第第2版版)Java語言程序設計語言程序設計(第第2版版)Java語言程序設計語言程序設計(第第2版版)Java語言程序設計語言程序設計(第第2版版)Java語言程序設計語言程序設計(第第2版版)Chopstick和Philosopher都使用一個自動增加的靜態(tài)計數(shù)器,來給每個元素一個標識數(shù)字。每個Philosopher對象都有一個對

42、左邊和右邊Chopstick對象的引用;這些是哲學家進餐之前必須得到的餐具。Java語言程序設計語言程序設計(第第2版版)靜態(tài)字段ponder表示哲學家是否花費時間進行思考。如果值是非零的,那么在think( )方法里線程將休眠一段由這個值隨機產(chǎn)生的時間。通過這種方法,就可以展示,線程(哲學家)在其它任務(思考)上花費的時越多,那么它們在請求共享資源(筷子)的時候發(fā)生沖突的可能性就越低,這樣你就能確信程序沒有死鎖,盡管事實上可能是有的。Java語言程序設計語言程序設計(第第2版版)在eat( )里,哲學家通過同步控制獲取左邊的筷子。如果筷子不可用,那么哲學家將等待(阻塞)。在獲取了左邊的筷子之后,再用同樣的方法獲取右邊的筷子。在就餐完畢之后,先釋放右邊的筷子,然后釋放左邊的筷子。在run( )中,每個哲學家不斷重復思考和就餐的動作。Java語言程序設計語言程序設計(第第2版版)main( )方法至少需要三個參數(shù),如果不滿足的話,就打印一條使用信息。第三個參數(shù)可以是字符串“deadlock”,在這種情況下,使用會發(fā)生死鎖的程序。如果是其它字符串就使用不產(chǎn)生死鎖的程序。最后一個參數(shù)(可選的)是一個到期因子,表示一段時間之后將退出程序(無論是否發(fā)生了死鎖)。作為本書所附代碼的測試程序的一部分,并且是自動運行的程序,設置一個過期時間是很有必要的。Java語言程序設計語言程

溫馨提示

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

評論

0/150

提交評論