Java类库中包含许多有用的“基础模块”类。通常应该优先选择重用这些类而不是开发新类:重用能降低开发工作量、开发风险以及维护成本。很多情况这些现有的类只能提供大部分工作,我们需要在不破坏线程安全的情况下添加一些新的操作。
这种方法最简单最安全。但通常情况下无法访问或修改类的源代码。
下面的代码中BetterVector扩展了Vector,并添加了新方法putIfAbsent。但并非所有的类都像Vector那样将状态向子类公开,因此也就不适合采用这种方法。
public class BetterVector<E> extends Vector<E>{
public synchronized boolean putIfAbsent(E e){
boolean absent = !contains(x);
if(absent)
add(x);
return absent;
}
}
扩展类的功能,而不是类本身(将扩展代码放在一个“辅助类”中)。
public class ListHelper<E>{
public List<E> list = Collection.synchronizedList(new ArrayList<E>());
...
public boolean putIfAbsent(E e){
synchronized(list){
boolean absent = !contains(x);
if(absent)
add(x);
return absent;
}
}
}
通过添加一个原子操作来扩展类是脆弱的,因为它将类的加锁代码分布到多个类中。客户端加锁机制更加脆弱,因为它将类C的加锁代码放到了与C完全无关的其他类中。
下列代码中ImprovedList通过将List对象的操作委托给低层的List实例来实现List操作,同时还添加了一个原子的putIfAbsent方法。
public class ImprovedList<T> implements List<T>{
private final List<T> list;
public ImprovedList(List<T> list){ this.list = list; }
public synchronized boolean putIfAbsent(T x){
boolean contains = list.contains(x);
if(contains)
list.add(x);
return !contains;
}
public synchronized void clear(){ list.clear(); }
//按照类似的方式委托List的其他方法
//...
}
ImprovedList通过自身的内置锁增加了一层额外的锁。他并不关心底层的List是否是线程安全的,即使List不是线程安全的或者修改了它的加锁实现,ImprovedList也会提供一致的加锁机制来实现线程安全性。