Effective Java 第三版—— 84. 不要依賴線程調度器


Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼里方法是基於Java 9 API中的,所以JDK 最好下載 JDK 9以上的版本。

Effective Java, Third Edition

84. 不要依賴線程調度器

當許多線程可以運行時,線程調度器(thread scheduler)決定哪些線程可以運行以及運行多長時間。任何合理的操作系統都會嘗試公平地做出這個決定,但是策略可能會有所不同。因此,編寫良好的程序不應該依賴於此策略的細節。任何依賴線程調度器來保證正確性或性能的程序都可能是不可移植的

編寫健壯,響應迅速的可移植程序的最佳方法是確保可運行線程的平均數量不會明顯大於處理器數量。 這使得線程調度程序幾乎沒有多少選擇:它只是運行可運行的線程,直到它們不再可運行為止。 即使在完全不同的線程調度策略下,程序的行為也不會有太大變化。 請注意,可運行線程的數量與線程總數不同,后者可能要高得多。 正在等待的線程不可運行。

保持可運行線程數量較少的主要技術是讓每個線程做一些有用的工作,然后等待更多的工作。 如果線程沒有做有用的工作,它們就不應該運行。 就Executor Framework而言(條目 80),這意味着適當調整線程池的大小[Goetz06, 8.2],並保持任務簡短,但不要太短,否則分派的開銷會損害性能。

線程不應該處於 busy-wait的狀態,反復檢查等待其狀態改變的共享對象。 除了使程序容易受到線程調度程序的變化無常的影響之外,一直處於 busy-wait的狀態大大增加了處理器的負擔,減少了其他人可以完成的有用工作量。 作為不該做的極端例子,請考慮CountDownLatch的這種不正當的重新實現:

// Awful CountDownLatch implementation - busy-waits incessantly!
public class SlowCountDownLatch {
    private int count;

    public SlowCountDownLatch(int count) {
        if (count < 0)
            throw new IllegalArgumentException(count + " < 0");
        this.count = count;
    }

    public void await() {
        while (true) {
            synchronized(this) {
                if (count == 0)
                    return;
            }
        }
    }

    public synchronized void countDown() {
        if (count != 0)
            count--;
    }
}

在我的機器上,當1000個線程在鎖存器(latch)上等待時,SlowCountDownLatch比Java的CountDownLatch慢大約十倍。 雖然這個例子看起來有點牽強,但是看到系統中有一個或多個線程不必要地運行,這種情況並不罕見。 性能和可移植性可能會受到影響。

當一個程序因為某些線程沒有獲得足夠的CPU時間而無法正常工作時,不要試圖通過調用Thread.yield方法來“修復”這個程序。你可能會成功地使程序在某種程度上工作,但它不會是可移植的。在一個JVM實現上提高性能的相同的yield方法調用,在第二個JVM實現上可能會使性能變差,而在第三個JVM實現上沒有任何影響。Thread.yield沒有可測試的語義。更好的做法是重構應用程序,以減少並發運行線程的數量。

類似警告適用的相關技術是調整線程優先級。 線程優先級是Java中最不可移植的功能之一。 通過調整一些線程優先級來調整應用程序的響應性並不是不合理的,但它很少是必需的,並且不可移植。 嘗試通過調整線程優先級來解決嚴重的活躍度問題是不合理的。 在你找到並解決根本原因之前,問題可能會重新出現。

總之,不要依賴線程調度器來確定程序的正確性。 由此產生的程序既不健壯也不可移植。 作為推論,不要依賴Thread.yield方法或線程優先級。 這些機制僅僅是對調度器的提示。 可以謹慎地使用線程優先級來提高已經工作的程序的服務質量,但是它們永遠不應該用於“修復”幾乎不起作用的程序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM