關於解決 Java 程式語言執行緒問題的建議(4)(轉)
關於解決 Java 程式語言執行緒問題的建議(4)(轉)[@more@]訪問的問題
如果缺少良好的訪問控制,會使執行緒程式設計非常困難。大多數情況下,如果能保證執行緒只從同步子系統中呼叫,不必考慮執行緒安全(threadsafe)問題。我建議對
Java 程式語言的訪問許可權概念做如下限制;
應精確使用 package
關鍵字來限制包訪問權。我認為當預設行為的存在是任何一種計算機語言的一個瑕疵,我對現在存在這種預設許可權感到很迷惑(而且這種預設是“包(package)”級別的而不是“私有(private)”)。
在其它方面,Java 程式語言都不提供等同的預設關鍵字。雖然使用顯式的 package
的限定詞會破壞現有程式碼,但是它將使程式碼的可讀性更強,並能消除整個類的潛在錯誤
(例如,如果訪問權是由於錯誤被忽略,而不是被故意忽略)。
重新引入 private protected,它的功能應和現在的 protected
一樣,但是不應允許包級別的訪問。
允許 private private 語法指定“實現的訪問”對於所有外部物件是私有的,甚至是當前物件是的同一個類的。對於“.”左邊的唯一引用(隱式或顯式)應是
this。
擴充套件 public 的語法,以授權它可制定特定類的訪問。例如,下面的程式碼應允許
Fred 類的物件可呼叫 some_method(),但是對其它類的物件,這個方法應是私有的。
public(Fred) void some_method()
{
}
這種建議不同於 C++ 的 "friend" 機制。 在 "friend" 機制中,它授權一個類訪問另一個類的所有私有部分。在這裡,我建議對有限的方法集合進行嚴格控制的訪問。用這種方法,一個類可以為另一個類定義一個介面,而這個介面對系統的其餘類是不可見的。一個明顯的變化是:
public(Fred, Wilma) void some_method()
{
}
除非域引用的是真正不變(immutable)的物件或 static final 基本型別,否則所有域的定義應是
private。 對於一個類中域的直接訪問違反了 OO 設計的兩個基本規則:抽象和封裝。從執行緒的觀點來看,允許直接訪問域只使對它進行非同步訪問更容易一些。
增加 $property 關鍵字。帶有此關鍵字的物件可被一個“bean
盒”應用程式訪問,這個程式使用在 Class 類中定義的反射操作(introspection) API,否則與 private private 同效。 $property
屬性可用在域和方法,這樣現有的 JavaBean getter/setter 方法可以很容易地被定義為屬性。
不變性(immutability)
由於對不變物件的訪問不需要同步,所以在多執行緒條件下,不變的概念(一個物件的值在建立後不可更改)是無價的。Java
程式設計言語中,對於不變性的實現不夠嚴格,有兩個原因:
對於一個不變物件,在其被未完全建立之前,可以對它進行訪問。這種訪問對於某些域可以產生不正確的值。
對於恆定 (類的所有域都是 final) 的定義太鬆散。對於由
final 引用指定的物件,雖然引用本身不能改變,但是物件本身可以改變狀態。
第一個問題可以解決,不允許執行緒在建構函式中開始執行
(或者在建構函式返回之前不能執行開始請求)。
對於第二個問題,透過限定 final 修飾符指向恆定物件,可以解決此問題。這就是說,對於一個物件,只有所有的域是
final,並且所有引用的物件的域也都是 final,此物件才真正是恆定的。為了不打破現有程式碼,這個定義可以使用編譯器加強,即只有一個類被顯式標為不變時,此類才是不變類。方法如下:
$immutable public class Fred
{
// all fields in this class must be final, and if the
// field is a reference, all fields in the referenced
// class must be final as well (recursively).
static int x constant = 0; // use of `final` is optional when $immutable
// is present.
}
有了 $immutable 修飾符後,在域定義中的 final 修飾符是可選的。
最後,當使用內部類(inner class)後,在 Java 編譯器中的一個錯誤使它無法可靠地建立不變物件。當一個類有重要的內部類時(我的程式碼常有),編譯器經常不正確地顯示下列錯誤資訊:
"Blank final variable ´name´ may not have been initialized.
It must be assigned a value in an initializer, or in every constructor."
既使空的 final 在每個建構函式中都有初始化,還是會出現這個錯誤資訊。自從在
1.1 版本中引入內部類後,編譯器中一直有這個錯誤。在此版本中(三年以後),這個錯誤依然存在。現在,該是改正這個錯誤的時候了。
對於類級域的例項級訪問
除了訪問許可權外,還有一個問題,即類級(靜態)方法和例項(非靜態)方法都能直接訪問類級(靜態)域。這種訪問是非常危險的,因為例項方法的同步不會獲取類級的鎖,所以一個
synchronized static 方法和一個 synchronized
方法還是能同時訪問類的域。改正此問題的一個明顯的方法是,要求在例項方法中只有使用
static 訪問方法才能訪問非不變類的 static
域。當然,這種要求需要編譯器和執行時間檢查。在這種規定下,下面的程式碼是非法的:
class Broken
{
static long x;
synchronized static void f()
{ x = 0;
}
synchronized void g()
{ x = -1;
}
};
由於 f() 和 g()
可以並行執行,所以它們能同時改變 x
的值(產生不定的結果)。請記住,這裡有兩個鎖:static
方法要求屬於 Class 物件的鎖,而非靜態方法要求屬於此類例項的鎖。當從例項方法中訪問非不變 static 域時,編譯器應要求滿足下面兩個結構中的任意一個:
class Broken
{
static long x;
synchronized private static accessor( long value )
{ x = value;
}
synchronized static void f()
{ x = 0;
}
synchronized void g()
{ accessor( -1 );
}
}
或則,編譯器應獲得讀/寫鎖的使用:
class Broken
{
static long x;
synchronized static void f()
{ $writing(x){ x = 0 };
}
synchronized void g()
{ $writing(x){ x = -1 };
}
}
另外一種方法是(這也是一種理想的方法)-- 編譯器應自動使用一個讀/寫鎖來同步訪問非不變 static 域,這樣,程式設計師就不必擔心這個問題。
後臺執行緒的突然結束
當所有的非後臺執行緒終止後,後臺執行緒都被突然結束。當後臺執行緒建立了一些全域性資源(例如一個資料庫連線或一個臨時檔案),而後臺執行緒結束時這些資源沒有被關閉或刪除就會導致問題。
對於這個問題,我建議制定規則,使 Java 虛擬機器在下列情況下不關閉應用程式:
有任何非後臺執行緒正在執行,或者:
有任何後臺執行緒正在執行一個 synchronized 方法或 synchronized 程式碼塊。
後臺執行緒在它執行完 synchronized 塊或 synchronized 方法後可被立即關閉。
重新引入 stop()、
suspend() 和 resume()
關鍵字
由於實用原因這也許不可行,但是我希望不要廢除 stop() (在 Thread 和 ThreadGroup 中)。但是,我會改變 stop()
的語義,使得呼叫它時不會破壞已有程式碼。但是,關於 stop() 的問題,請記住,當執行緒終止後,stop()
將釋放所有鎖,這樣可能潛在地使正在此物件上工作的執行緒進入一種不穩定(區域性修改)的狀態。由於停止的執行緒已釋放它在此物件上的所有鎖,所以這些物件無法再被訪問。
對於這個問題,可以重新定義 stop() 的行為,使執行緒只有在不佔有任何鎖時才立即終止。如果它佔據著鎖,我建議在此執行緒釋放最後一個鎖後才終止它。
可以使用一個和丟擲異常相似的機制來實現此行為。被停止執行緒應設定一個標誌,並且當退出所有同步塊時立即測試此標誌。如果設定了此標誌,就丟擲一個隱式的異常,
但是此異常應不再能被捕捉並且當執行緒結束時不會產生任何輸出。注意,微軟的 NT 作業系統不能很好地處理一個外部指示的突然停止(abrupt)。(它不把
stop 訊息通知動態連線庫,所以可能導致系統級的資源漏洞。)這就是我建議使用類似異常的方法簡單地導致 run() 返回的原因。
與這種和異常類似的處理方法帶來的實際問題是,你必需在每個 synchronized
塊後都插入程式碼來測試“stopped”標誌。並且這種附加的程式碼會降低系統效能並增加程式碼長度。我想到的另外一個辦法是使 stop()
實現一個“延遲的(lazy)”停止,在這種情況下,在下次呼叫 wait()
或 yield() 時才終止。我還想向 Thread
中加入一個 isStopped() 和 stopped() 方法
(此時,Thread 將像isInterrupted() 和 interrupted()
一樣工作,但是會檢測 “stop-requested”的狀態)。這種方法不向第一種那樣通用,但是可行並且不會產生過載。
應把 suspend() 和 resume() 方法放回到 Java
程式語言中,它們是很有用的,我不想被當成是幼兒園的小孩。由於它們可能產生潛在的危險(當被掛起時,一個執行緒可以佔據一個鎖)而去掉它們是沒有道理的。請讓我自己來決定是否使用它們。
如果接收的執行緒正佔據著鎖,Sun 公司應該把它們作為呼叫 suspend() 的一個執行時間異常處理(run-time exception);或者更好的方法是,延遲實際的掛起過程,直到執行緒釋放所有的鎖。
被阻斷的 I/O 應正確工作
應該能打斷任何被阻斷的操作,而不是隻讓它們 wait()
和 sleep()。我在“Taming Java Threads”的第二章中的 socket 部分討論了此問題。但是現在,對於一個被阻斷的 socket 上的
I/O 操作,打斷它的唯一辦法是關閉這個 socket,而沒有辦法打斷一個被阻斷的檔案 I/O 操作。例如,一旦開始一個讀請求並且進入阻斷狀態後,除非到它實際讀出一些東西,
否則執行緒一直出於阻斷狀態。既使關掉檔案控制程式碼也不能打斷讀操作。
還有,程式應支援 I/O 操作的超時。所有可能出現阻斷操作的物件(例如 InputStream 物件)也都應支援這種方法:
InputStream s = ...;
s.set_timeout( 1000 );
這和 Socket 類的 setSoTimeout(time)
方法是等價的。同樣地,應該支援把超時作為引數傳遞到阻斷的呼叫。
ThreadGroup 類
ThreadGroup 應該實現 Thread 中能夠改變執行緒狀態的所有方法。我特別想讓它實現 join() 方法,這樣我就可等待組中的所有執行緒的終止。
總結
以上是我的建議。就像我在標題中所說的那樣,如果我是國王...(哎)。我希望這些改變(或其它等同的方法)最終能被引入
Java 語言中。我確實認為 Java 語言是一種偉大的程式語言;但是我也認為 Java 的執行緒模型設計得還不夠完善,這是一件很可惜的事情。但是,Java
程式語言正在演變,所以還有可提高的前景。
參考資料
本文是對 Taming Java Threads 的更新摘編。該書
探討了在 Java 語言中多執行緒程式設計的陷阱和問題,並提供了一個與執行緒相關的 Java 程式包來解決這些問題。
馬里蘭大學的 Bill Pugh 正在致力修改 JLS 來提高其執行緒模型。Bill 的提議並不如本文所推薦的那麼廣,他主要致力於讓現有的執行緒模型以更為合理方式執行。更多資訊可從 獲得。
從 Sun 網站可找到全部 Java 語言的規範。
要從一個純技術角度來審視執行緒,參閱 Doug Lea 編著的 Concurrent Programming in Java: Design Principles and Patterns 第二版。這是本很棒的書,但是它的風格是非常學術化的並不一定適合所有的讀者。對《Taming Java Threads》是個很好的補充讀物。
由 Scott Oaks 和 Henry Wong 編寫的 Java Threads 比 Taming Java Threads 要輕量些,但是如果您從未編寫過執行緒程式這本書更為適合。Oaks 和 Wong 同樣實現了 Holub 提供的幫助類,而且看看對同一問題的不同解決方案總是有益的。
由 Bill Lewis 和 Daniel J. Berg 編寫的 Threads Primer: A Guide to Multithreaded Programming 是對執行緒(不限於 Java)的很好入門介紹。
Java 執行緒的一些技術資訊可在 Sun 網站上找到。
在 "Multiprocessor Safety and Java" 中 Paul Jakubik 討論了多執行緒系統的 SMP 問題。
作者簡介
Allen Holub 從 1979 年起就開始致力於計算機行業。他在各種雜誌
(Dr. Dobb´s Journal、Programmers Journal、 Byte、MSJ 和其它雜誌) 上發表了大量的文章。他為網路雜誌
JavaWorld 撰寫 “Java
工具箱”專欄,也為 IBM
developerWorks 元件技術專區 撰寫“OO-設計流程”欄目。他還領導著
ITWorld 程式設計理論和實踐討論組。
Allen 撰寫了八本書籍,最近新出的一本討論了 Java 執行緒的陷阱和缺陷《Taming Java Threads》。他長期從事設計和編制物件導向軟體。從事了
8 年的 C++ 程式設計工作後,Allen 在 1996 年由 C++ 轉向 Java。他現在視 C++ 為一個噩夢,其可怕的經歷正被逐漸淡忘。他從 1982 年起就自己和為加利弗尼亞大學伯克利分校教授計算機程式設計(首先是
C,然後是 C++ 和 MFC,現在是物件導向設計和 Java)。 Allen 也提供 Java 和麵向物件設計方面的公眾課程和私授 (in-house) 課程。他還提供物件導向設計的諮詢並承包 Java 程式設計專案。請透過此 Web 站點和 Allen 取得聯絡並獲取資訊:。
如果缺少良好的訪問控制,會使執行緒程式設計非常困難。大多數情況下,如果能保證執行緒只從同步子系統中呼叫,不必考慮執行緒安全(threadsafe)問題。我建議對
Java 程式語言的訪問許可權概念做如下限制;
應精確使用 package
關鍵字來限制包訪問權。我認為當預設行為的存在是任何一種計算機語言的一個瑕疵,我對現在存在這種預設許可權感到很迷惑(而且這種預設是“包(package)”級別的而不是“私有(private)”)。
在其它方面,Java 程式語言都不提供等同的預設關鍵字。雖然使用顯式的 package
的限定詞會破壞現有程式碼,但是它將使程式碼的可讀性更強,並能消除整個類的潛在錯誤
(例如,如果訪問權是由於錯誤被忽略,而不是被故意忽略)。
重新引入 private protected,它的功能應和現在的 protected
一樣,但是不應允許包級別的訪問。
允許 private private 語法指定“實現的訪問”對於所有外部物件是私有的,甚至是當前物件是的同一個類的。對於“.”左邊的唯一引用(隱式或顯式)應是
this。
擴充套件 public 的語法,以授權它可制定特定類的訪問。例如,下面的程式碼應允許
Fred 類的物件可呼叫 some_method(),但是對其它類的物件,這個方法應是私有的。
public(Fred) void some_method()
{
}
這種建議不同於 C++ 的 "friend" 機制。 在 "friend" 機制中,它授權一個類訪問另一個類的所有私有部分。在這裡,我建議對有限的方法集合進行嚴格控制的訪問。用這種方法,一個類可以為另一個類定義一個介面,而這個介面對系統的其餘類是不可見的。一個明顯的變化是:
public(Fred, Wilma) void some_method()
{
}
除非域引用的是真正不變(immutable)的物件或 static final 基本型別,否則所有域的定義應是
private。 對於一個類中域的直接訪問違反了 OO 設計的兩個基本規則:抽象和封裝。從執行緒的觀點來看,允許直接訪問域只使對它進行非同步訪問更容易一些。
增加 $property 關鍵字。帶有此關鍵字的物件可被一個“bean
盒”應用程式訪問,這個程式使用在 Class 類中定義的反射操作(introspection) API,否則與 private private 同效。 $property
屬性可用在域和方法,這樣現有的 JavaBean getter/setter 方法可以很容易地被定義為屬性。
不變性(immutability)
由於對不變物件的訪問不需要同步,所以在多執行緒條件下,不變的概念(一個物件的值在建立後不可更改)是無價的。Java
程式設計言語中,對於不變性的實現不夠嚴格,有兩個原因:
對於一個不變物件,在其被未完全建立之前,可以對它進行訪問。這種訪問對於某些域可以產生不正確的值。
對於恆定 (類的所有域都是 final) 的定義太鬆散。對於由
final 引用指定的物件,雖然引用本身不能改變,但是物件本身可以改變狀態。
第一個問題可以解決,不允許執行緒在建構函式中開始執行
(或者在建構函式返回之前不能執行開始請求)。
對於第二個問題,透過限定 final 修飾符指向恆定物件,可以解決此問題。這就是說,對於一個物件,只有所有的域是
final,並且所有引用的物件的域也都是 final,此物件才真正是恆定的。為了不打破現有程式碼,這個定義可以使用編譯器加強,即只有一個類被顯式標為不變時,此類才是不變類。方法如下:
$immutable public class Fred
{
// all fields in this class must be final, and if the
// field is a reference, all fields in the referenced
// class must be final as well (recursively).
static int x constant = 0; // use of `final` is optional when $immutable
// is present.
}
有了 $immutable 修飾符後,在域定義中的 final 修飾符是可選的。
最後,當使用內部類(inner class)後,在 Java 編譯器中的一個錯誤使它無法可靠地建立不變物件。當一個類有重要的內部類時(我的程式碼常有),編譯器經常不正確地顯示下列錯誤資訊:
"Blank final variable ´name´ may not have been initialized.
It must be assigned a value in an initializer, or in every constructor."
既使空的 final 在每個建構函式中都有初始化,還是會出現這個錯誤資訊。自從在
1.1 版本中引入內部類後,編譯器中一直有這個錯誤。在此版本中(三年以後),這個錯誤依然存在。現在,該是改正這個錯誤的時候了。
對於類級域的例項級訪問
除了訪問許可權外,還有一個問題,即類級(靜態)方法和例項(非靜態)方法都能直接訪問類級(靜態)域。這種訪問是非常危險的,因為例項方法的同步不會獲取類級的鎖,所以一個
synchronized static 方法和一個 synchronized
方法還是能同時訪問類的域。改正此問題的一個明顯的方法是,要求在例項方法中只有使用
static 訪問方法才能訪問非不變類的 static
域。當然,這種要求需要編譯器和執行時間檢查。在這種規定下,下面的程式碼是非法的:
class Broken
{
static long x;
synchronized static void f()
{ x = 0;
}
synchronized void g()
{ x = -1;
}
};
由於 f() 和 g()
可以並行執行,所以它們能同時改變 x
的值(產生不定的結果)。請記住,這裡有兩個鎖:static
方法要求屬於 Class 物件的鎖,而非靜態方法要求屬於此類例項的鎖。當從例項方法中訪問非不變 static 域時,編譯器應要求滿足下面兩個結構中的任意一個:
class Broken
{
static long x;
synchronized private static accessor( long value )
{ x = value;
}
synchronized static void f()
{ x = 0;
}
synchronized void g()
{ accessor( -1 );
}
}
或則,編譯器應獲得讀/寫鎖的使用:
class Broken
{
static long x;
synchronized static void f()
{ $writing(x){ x = 0 };
}
synchronized void g()
{ $writing(x){ x = -1 };
}
}
另外一種方法是(這也是一種理想的方法)-- 編譯器應自動使用一個讀/寫鎖來同步訪問非不變 static 域,這樣,程式設計師就不必擔心這個問題。
後臺執行緒的突然結束
當所有的非後臺執行緒終止後,後臺執行緒都被突然結束。當後臺執行緒建立了一些全域性資源(例如一個資料庫連線或一個臨時檔案),而後臺執行緒結束時這些資源沒有被關閉或刪除就會導致問題。
對於這個問題,我建議制定規則,使 Java 虛擬機器在下列情況下不關閉應用程式:
有任何非後臺執行緒正在執行,或者:
有任何後臺執行緒正在執行一個 synchronized 方法或 synchronized 程式碼塊。
後臺執行緒在它執行完 synchronized 塊或 synchronized 方法後可被立即關閉。
重新引入 stop()、
suspend() 和 resume()
關鍵字
由於實用原因這也許不可行,但是我希望不要廢除 stop() (在 Thread 和 ThreadGroup 中)。但是,我會改變 stop()
的語義,使得呼叫它時不會破壞已有程式碼。但是,關於 stop() 的問題,請記住,當執行緒終止後,stop()
將釋放所有鎖,這樣可能潛在地使正在此物件上工作的執行緒進入一種不穩定(區域性修改)的狀態。由於停止的執行緒已釋放它在此物件上的所有鎖,所以這些物件無法再被訪問。
對於這個問題,可以重新定義 stop() 的行為,使執行緒只有在不佔有任何鎖時才立即終止。如果它佔據著鎖,我建議在此執行緒釋放最後一個鎖後才終止它。
可以使用一個和丟擲異常相似的機制來實現此行為。被停止執行緒應設定一個標誌,並且當退出所有同步塊時立即測試此標誌。如果設定了此標誌,就丟擲一個隱式的異常,
但是此異常應不再能被捕捉並且當執行緒結束時不會產生任何輸出。注意,微軟的 NT 作業系統不能很好地處理一個外部指示的突然停止(abrupt)。(它不把
stop 訊息通知動態連線庫,所以可能導致系統級的資源漏洞。)這就是我建議使用類似異常的方法簡單地導致 run() 返回的原因。
與這種和異常類似的處理方法帶來的實際問題是,你必需在每個 synchronized
塊後都插入程式碼來測試“stopped”標誌。並且這種附加的程式碼會降低系統效能並增加程式碼長度。我想到的另外一個辦法是使 stop()
實現一個“延遲的(lazy)”停止,在這種情況下,在下次呼叫 wait()
或 yield() 時才終止。我還想向 Thread
中加入一個 isStopped() 和 stopped() 方法
(此時,Thread 將像isInterrupted() 和 interrupted()
一樣工作,但是會檢測 “stop-requested”的狀態)。這種方法不向第一種那樣通用,但是可行並且不會產生過載。
應把 suspend() 和 resume() 方法放回到 Java
程式語言中,它們是很有用的,我不想被當成是幼兒園的小孩。由於它們可能產生潛在的危險(當被掛起時,一個執行緒可以佔據一個鎖)而去掉它們是沒有道理的。請讓我自己來決定是否使用它們。
如果接收的執行緒正佔據著鎖,Sun 公司應該把它們作為呼叫 suspend() 的一個執行時間異常處理(run-time exception);或者更好的方法是,延遲實際的掛起過程,直到執行緒釋放所有的鎖。
被阻斷的 I/O 應正確工作
應該能打斷任何被阻斷的操作,而不是隻讓它們 wait()
和 sleep()。我在“Taming Java Threads”的第二章中的 socket 部分討論了此問題。但是現在,對於一個被阻斷的 socket 上的
I/O 操作,打斷它的唯一辦法是關閉這個 socket,而沒有辦法打斷一個被阻斷的檔案 I/O 操作。例如,一旦開始一個讀請求並且進入阻斷狀態後,除非到它實際讀出一些東西,
否則執行緒一直出於阻斷狀態。既使關掉檔案控制程式碼也不能打斷讀操作。
還有,程式應支援 I/O 操作的超時。所有可能出現阻斷操作的物件(例如 InputStream 物件)也都應支援這種方法:
InputStream s = ...;
s.set_timeout( 1000 );
這和 Socket 類的 setSoTimeout(time)
方法是等價的。同樣地,應該支援把超時作為引數傳遞到阻斷的呼叫。
ThreadGroup 類
ThreadGroup 應該實現 Thread 中能夠改變執行緒狀態的所有方法。我特別想讓它實現 join() 方法,這樣我就可等待組中的所有執行緒的終止。
總結
以上是我的建議。就像我在標題中所說的那樣,如果我是國王...(哎)。我希望這些改變(或其它等同的方法)最終能被引入
Java 語言中。我確實認為 Java 語言是一種偉大的程式語言;但是我也認為 Java 的執行緒模型設計得還不夠完善,這是一件很可惜的事情。但是,Java
程式語言正在演變,所以還有可提高的前景。
參考資料
本文是對 Taming Java Threads 的更新摘編。該書
探討了在 Java 語言中多執行緒程式設計的陷阱和問題,並提供了一個與執行緒相關的 Java 程式包來解決這些問題。
馬里蘭大學的 Bill Pugh 正在致力修改 JLS 來提高其執行緒模型。Bill 的提議並不如本文所推薦的那麼廣,他主要致力於讓現有的執行緒模型以更為合理方式執行。更多資訊可從 獲得。
從 Sun 網站可找到全部 Java 語言的規範。
要從一個純技術角度來審視執行緒,參閱 Doug Lea 編著的 Concurrent Programming in Java: Design Principles and Patterns 第二版。這是本很棒的書,但是它的風格是非常學術化的並不一定適合所有的讀者。對《Taming Java Threads》是個很好的補充讀物。
由 Scott Oaks 和 Henry Wong 編寫的 Java Threads 比 Taming Java Threads 要輕量些,但是如果您從未編寫過執行緒程式這本書更為適合。Oaks 和 Wong 同樣實現了 Holub 提供的幫助類,而且看看對同一問題的不同解決方案總是有益的。
由 Bill Lewis 和 Daniel J. Berg 編寫的 Threads Primer: A Guide to Multithreaded Programming 是對執行緒(不限於 Java)的很好入門介紹。
Java 執行緒的一些技術資訊可在 Sun 網站上找到。
在 "Multiprocessor Safety and Java" 中 Paul Jakubik 討論了多執行緒系統的 SMP 問題。
作者簡介
Allen Holub 從 1979 年起就開始致力於計算機行業。他在各種雜誌
(Dr. Dobb´s Journal、Programmers Journal、 Byte、MSJ 和其它雜誌) 上發表了大量的文章。他為網路雜誌
JavaWorld 撰寫 “Java
工具箱”專欄,也為 IBM
developerWorks 元件技術專區 撰寫“OO-設計流程”欄目。他還領導著
ITWorld 程式設計理論和實踐討論組。
Allen 撰寫了八本書籍,最近新出的一本討論了 Java 執行緒的陷阱和缺陷《Taming Java Threads》。他長期從事設計和編制物件導向軟體。從事了
8 年的 C++ 程式設計工作後,Allen 在 1996 年由 C++ 轉向 Java。他現在視 C++ 為一個噩夢,其可怕的經歷正被逐漸淡忘。他從 1982 年起就自己和為加利弗尼亞大學伯克利分校教授計算機程式設計(首先是
C,然後是 C++ 和 MFC,現在是物件導向設計和 Java)。 Allen 也提供 Java 和麵向物件設計方面的公眾課程和私授 (in-house) 課程。他還提供物件導向設計的諮詢並承包 Java 程式設計專案。請透過此 Web 站點和 Allen 取得聯絡並獲取資訊:。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-958381/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 關於解決 Java 程式語言執行緒問題的建議(3)(轉)Java執行緒
- 關於解決 Java 程式語言執行緒問題的建議(2)(轉)Java執行緒
- 關於解決 Java 程式語言執行緒問題的建議(1)(轉)Java執行緒
- 小小問題―關於java多執行緒Java執行緒
- 關於執行緒的問題...執行緒
- 關於Mysql 4.1語言問題的完美解決方法(轉)MySql
- 關於js執行緒問題的解讀JS執行緒
- Java語言深入 多執行緒程式模型研究(轉)Java執行緒模型
- 關於執行緒的講解(出自Java原著)(轉)執行緒Java
- 關於java執行緒釋放資源問題Java執行緒
- java多執行緒程式設計問題以及解決辦法Java執行緒程式設計
- 【java 多執行緒】多執行緒併發同步問題及解決方法Java執行緒
- (轉貼)關於程式和執行緒 (轉)執行緒
- 多執行緒-執行緒安全問題的產生原因分析以及同步程式碼塊的方式解決執行緒安全問題執行緒
- Java中解決多執行緒資料安全問題Java執行緒
- Java中多執行緒的概述、實現方式、執行緒控制、生命週期、多執行緒程式練習、安全問題的解決...Java執行緒
- 請教一個關於執行緒的問題執行緒
- 關於執行緒的問題,清高手指點執行緒
- java多執行緒執行問題Java執行緒
- java 多執行緒(關於Thread的講解)Java執行緒thread
- 關於多執行緒(轉)執行緒
- 多執行緒-生產者消費者問題程式碼2並解決執行緒安全問題執行緒
- 關於多執行緒訪問靜態方法的問題執行緒
- java語言相關的問題Java
- 利用C語言小程式來解決大問題(轉)C語言
- java執行緒安全問題Java執行緒
- 多執行緒的安全問題及解決方案執行緒
- 有個關於多執行緒的識別問題執行緒
- 關於線上檢測主執行緒卡頓的問題執行緒
- 關於執行緒插入函式如何用的問題執行緒函式
- 請教關於執行緒的結束問題,急!!!執行緒
- 關於執行緒池的面試題執行緒面試題
- 40個關於Java多執行緒知識點問題總結Java執行緒
- [轉]Java執行緒詳解Java執行緒
- 關於C語言的面試問題C語言面試
- Java學習(28)—(執行緒的控制/生命週期/解決安全問題)Java執行緒
- 怎樣成為解決問題的高手?——關於問題解決的關鍵4步驟
- 多執行緒相關問題執行緒