1. 程式人生 > >已有的執行緒安全類中新增功能

已有的執行緒安全類中新增功能

現在我們要擴充套件一個list,不能破壞它原本的安全性以及相關不變約束和後驗條件,並且不能修改原始碼,該如何做呢。

通常首先想到的方法是繼承list,擴充套件程式碼;其次稍微深入的會用到同步包裝器,然後客戶端加鎖,這種方法一般是可以的;最後可能想到的是使用組合,進而制定一套管理併發訪問狀態變數的策略。接下來展示者三種方法:

方法一:使用繼承

public class BetterVector<E> extends Vector<E> {
    public synchronized boolean putIfAbsent(E x) {
        boolean absent = !contains(x);
        if (absent)
            add(x);
        return absent;
    }
}

這種方法可行的根本是擴充套件類的同步策略沒有破壞超類的同步協議。

方法二:使用同步包裝器

public class ListHelper<E> {
    public List<E> list =
            Collections.synchronizedList(new ArrayList<E>());

    public boolean putIfAbsent(E x) {
        synchronized (list) {
            boolean absent = list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
}

方法三:使用組合(最佳)

public class ImprovedList<T> implements List<T> {
    private final List<T> list;

    public ImprovedList(List<T> list) {this.list =list; }

    public synchronized boolean putlfAbsent(T x) {
        boolean contains = list.contains(x);
        if (contains)
            list.add(x);
        return !contains;
    }

    public synchronized void clear() {
        list.clear();
    }
    // ... similarly delegate other List methods
}

通過使用內部鎖, improvedLisc 引入了一個新的鎖層。它並不關心底層的 List 是否執行緒安全,即使 List 不是執行緒安全的',或者會改變 ImprovedList 的鎖實現,ImprovedList 都有自己相容的鎖可以提供執行緒安全性。 雖然額外的一層同步可能會帶來一些微弱的效能損失。 但是相比於去嘗試模擬另一個物件的鎖策略而言, ImprovedList並不那麼脆弱。 我們己經使用 Java 監視器模式有效地封裝了一個已有的 List, 而且只要我們的類持有底層 list的唯一外部引用, 那麼就能保證提供執行緒安仝性。