陷阱 - 擴充套件 java.lang.Thread
Thread
類的 javadoc 顯示了兩種定義和使用執行緒的方法:
使用自定義執行緒類:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
使用 Runnable
:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
(來源: java.lang.Thread
javadoc 。)
自定義執行緒類方法有效,但它有一些問題:
-
在使用經典執行緒池,執行器或 ForkJoin 框架的上下文中使用
PrimeThread
是很尷尬的。 (這並非不可能,因為PrimeThread
間接實現了Runnable
,但使用自定義的Thread
類作為Runnable
肯定是笨拙的,並且可能不可行……取決於類的其他方面。) -
其他方法存在更多錯誤的機會。例如,如果你在未委託
Thread.start()
的情況下宣告瞭PrimeThread.start()
,那麼你最終會得到一個在當前執行緒上執行的執行緒。
將執行緒邏輯放入 Runnable
的方法避免了這些問題。實際上,如果你使用匿名類(Java 1.1 以上)來實現 Runnable
,結果將比上面的示例更簡潔,更易讀。
final long minPrime = ...
new Thread(new Runnable() {
public void run() {
// compute primes larger than minPrime
. . .
}
}.start();
使用 lambda 表示式(Java 8 以後),上面的示例將變得更加優雅:
final long minPrime = ...
new Thread(() -> {
// compute primes larger than minPrime
. . .
}).start();