《21世紀高職高專教學做一體化規劃教材:Java程序設計》對面向對象的思想和機制進行了準確而透徹的剖析,為讀者深入學習Java語言程序設計提供了全面、詳細的指導。采用Java編程語言,詳細介紹了Java的程序邏輯、面向對象程序設計基礎、面向對象基本特性、常用對象的使用、異常處理、輸入輸出操作、多線程編程、GUI可視化界面編程等知識。使廣大讀者能夠掌握Java面向對象程序設計的基本技能。全書采取統一案例設計教學情境,每個章節是任務子情境分解,教材有機反映教學任務和工作任務,以真實工作任務帶動全書各章節,讓讀者身臨其境,真實感受過程。書中在每個子任務中都補充了針對本節主題的應用實踐,以滿足不同程度的讀者需求,并應用所學的技術解決實際應用程序開發中遇到的問題。
書摘/試閱
(2)生產者與消費者
系統中某一資源的線程稱為消費者線程,產生同一資源的線程稱為生產者線程。例如,在一個Java的應用程序中,生產者線程向文件中寫入數據,消費者線程從文件中讀取數據,這樣,在這個程序中同時運行的兩個線程共享同一個文件資源。
例如有一個簡單的例子,生產者產生從0~9的整數,將它們存儲在某個對象的成員變量contents中,并打印出產生的數據。然后調用sleep()方法使生產者線程在一定時間內休眠。消費者線程則不斷地從對象中讀取這些整數。
這個例子中生產者和消費者通過指定對象共享數據。不能保證的是生產者產生一個數,消費者就獲得這個數,并且只獲得一次。有可能出現的情況是:
第一種情況是生產者如果比消費者快,那么在消費者來不及取前一個數據之前,生產者又有了新數據。于是,消費者很有可能跳過前一個數據,直接讀取了新的數據。
第二種情況是,當消費者比生產者快時,消費者可能兩次取同一個數據。
為了避免這種情況發生,必須使生產者線程存儲數據和消費者線程讀取數據同步起來,兩個線程需要在以下兩個方面進行同步:
兩個線程不能同時訪問存儲數據的對象。兩個線程可以通過加鎖機制防止這種情況發生。兩個線程必須相互協作,生產者生產數據以后,要告訴消費者數據已準備好,可以取數據,生產者等待消費者取走數據。消費者取走數據后,要告訴生產者已取走數據,可以生產新數據。這需要調用wait()、notify0和notifyAll0方法來實現。
(3)死鎖問題
允許多個線程并發訪問共享資源時,必須提供同步機制,然而對這種機制使用不當的話,可能會出現線程永遠被阻塞的現象,當兩個或多個線程等待一個不可能滿足的條件時就發生死鎖。
Java語言本身既不能發現死鎖,也不能預防死鎖,只能靠程序員謹慎的設計來避免。一般來說,如果線程因為等待某個先決條件而受阻,它應該釋放所占的資源,讓其他線程使用。當先決條件滿足而恢復運行時,再重新獲得這些資源。避免死鎖的有效方法是,如果多個資源需要競爭訪問,應該確定線程訪問資源的順序,并且以相反的順序釋放資源。
7-2.5應用實踐
編寫一個Java應用程序,模擬銀行系統對用戶存款和取款的處理過程。假設存款人和取款人在同一時間對同一賬戶進行操作。賬戶原有余額是1000,存款人存入500,與此同時,取款人取走700,如果兩人操作是相對獨立的,那么存款人看到的賬戶余額是1500,而取款人看到的賬戶余額是300。顯然,同一賬戶不可能同時具有不同的余額,銀行系統必須保證同一時間內只有一個人可以對賬戶進行操作,這里需要使用線程的同步控制來實現。