中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Effective Java —— 并發篇 精華總結

發布時間:2020-08-10 10:40:00 來源:網絡 閱讀:330 作者:星恒Android 欄目:移動開發
同步訪問共享的可變數據

將可變數據限制在單個線程中
當多個線程共享可變數據,每個讀或者寫的線程都必須執行同步
如下例,去除同步鎖則會造成死循環

private static boolean stopRequested;
private static synchronized void requestStop() {
    stopRequested = true;
}

private static synchronized boolean stopRequested() {
    return stopRequested;
}

public static void main(String[] args) throws InterruptedException {
    Thread backgroundThread = new Thread(new Runnable() {
        @Override
        public void run() {
            int i = 0;
            while (!stopRequested()) {
                i++;
            }
        }
    });
    backgroundThread.start();
    TimeUnit.SECONDS.sleep(1);
    requestStop();
}
避免過度同步

多線程環境下,在觀察者模式中使用CopyOnWriteArrayList或CopyOnWriteArraySet(并發場景常用),可以避免死鎖,提高并發性。反之在遍歷中去修改原有的集合,則可能會導致異常。
在同步區域內,做盡可能少的事情。

executor和task優先于線程

大負載服務器:Executors.newFixedThreadPool(),并發過高需要限制線程總數
輕量級程序:Executors.newCachedThreadPool(),自動處理多數情況。
替代Timer:Executors.newScheduledThreadPool(),更為準確,支持多線程,并且能異常恢復。

取代notify和wait

使用并發集合和同步器,例如ConcurrentMap,無需使用notify和wait。
間歇性計時優先使用System.nanoTime,它將更精確并免受系統時鐘調整影響。
如果維護代碼,優先使用notifyAll(),避免不相關線程惡意等待。

線程安全文檔化

文檔注釋如下安全類型,而非簡單用synchronized判斷線程安全,需要注明調用時需要獲得哪一把鎖

1.不可變

不變的對象絕對是線程安全的,不需要線程同步,如String、Long、BigInteger

2.無條件的線程安全

對象自身做了 足夠的內部同步,也不需要外部同步,如 Random 、ConcurrentHashMap、Concurrent集合、atomic

3.有條件的線程安全

對象的部分方法可以無條件安全使用,但是有些方法需要外部同步,需要Collections.synchronized;有條件線程安全的最常見的例子是遍歷由 Hashtable 或者 Vector 或者返回的迭代器

4.非線程安全(線程兼容)

對象本身不提供線程安全機制,但是通過外部同步,可以在并發環境使用, 如ArrayList HashMap

5.線程對立

即使外部進行了同步調用,也不能保證線程安全,這種情況非常少,如如System.setOut()、System.runFinalizersOnExit()

慎用延遲初始化

大多數情況下使用正常初始化。
根據性能差距決定是否延遲初始化(懶加載)。當實例化開銷很高并只在部分域訪問的時候,可以考慮延遲初始化,同時在多線程下,需要考慮同步。
延遲初始化建議使用雙重檢查鎖(效率比單重大概高25%),并且變量聲明volatile。

private volatile FieldType field;
public FieldType getField() {
    FieldType result = field;
    if (result == null) {
        synchronized (this) {
            result = field;
            if (result == null) {
                field = result = computeFieldValue();
            }
        }
    }
    return result;
}

另一種方式是靜態域延遲初始化,原理是靜態內部類使用的時候才會進行初始化,并且無需使用同步。

private static class FieldHolder {
    static final FieldType field = computeFieldValue();
}

public static FieldType getField() {
    return FieldHolder.field;
}
不要依賴線程調度器

依賴線程調度器將使程序缺乏可移植性和健壯性,不依賴Thread.yield或者線程優先級。
程序原則是確保可運行線程平均數量不明顯多于處理器數量。

避免使用線程組

線程組(ThreadGroup)沒有提供它所提及的任何安全功能,不僅如此它提供的功能不完全而且有缺陷,請當它不存在吧。它的替代品是線程池。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长沙市| 旬阳县| 闻喜县| 太保市| 松阳县| 辉南县| 龙井市| 修水县| 胶南市| 西乌珠穆沁旗| 平和县| 高邮市| 浙江省| 西乡县| 十堰市| 姜堰市| 廉江市| 祥云县| 和龙市| 荣成市| 梁平县| 龙陵县| 锡林浩特市| 恩平市| 永寿县| 页游| 武邑县| 延吉市| 黑山县| 文安县| 河北省| 迁西县| 庆阳市| 柯坪县| 平远县| 霞浦县| 准格尔旗| 图木舒克市| 额尔古纳市| 宁城县| 信宜市|