实例封闭
将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁
- java类库中有很多线程封闭示例: Collections.synchronizedList及其类似方法,这些工厂方法通过装饰器(Decorator)设计模式将容器类封装在一个同步的包装容器对象中
//通过封闭机制来确保线程安全
public class PersonSet {
//将数据封装在对象内部
private final Set<Person> mySet = new HashSet<Person>();
//数据访问只能通过此同步方法进行
public synchronized void addPerson(Person p) {
mySet.add(p);
}
//数据访问只能通过此同步方法进行
public synchronized boolean containsPerson(Person p) {
return mySet.contains(p);
}
interface Person {
}
}
监视器模式
遵循java监视器模式的对象会把对象的所有可变状态都封装起来,并由对象自己的内置锁来保护,例如Vector和HashTable
//监视器模式: 通过一个私有锁来保护状态
public class PrivateLock {
private final Object myLock = new Object();
Widget widget; //要封装的对象widget
void someMethod() {
synchronized (myLock) { //由内置锁(监视器)保护
// 访问或修改widget对象状态
}
}
}
线程安全性的委托
如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量
//将线程安全性委托给多个状态变量
public class VisualComponent {
//两个事件监听器之间不存在任何关联,将VisualComponent类的线程安全性委托给这两个线程安全的监听器列表
//由CopyOnWriteArrayList管理保证线程安全性
private final List<KeyListener> keyListeners = new CopyOnWriteArrayList<KeyListener>();
private final List<MouseListener> mouseListeners = new CopyOnWriteArrayList<MouseListener>();
public void addKeyListener(KeyListener listener) {
keyListeners.add(listener);
}
public void addMouseListener(MouseListener listener) {
mouseListeners.add(listener);
}
public void removeKeyListener(KeyListener listener) {
keyListeners.remove(listener);
}
public void removeMouseListener(MouseListener listener) {
mouseListeners.remove(listener);
}
}
现有的线程安全类中添加功能
- 扩展类
//没有则添加: 继承然后扩展类
public class BetterVector <E> extends Vector<E> {
//对于一个继承了serializable的类,应该重新定义其serialVersionUID
static final long serialVersionUID = -3963416950630760754L;
//不存在时添加: 增加一个原子方法(使用同步锁)
public synchronized boolean putIfAbsent(E x) {
boolean absent = !contains(x);
if (absent)
add(x);
return absent;
}
}
- 客户端加锁机制
//没有则添加: 通过客户端加锁方式实现
class GoodListHelper <E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public boolean putIfAbsent(E x) {
synchronized (list) { //锁对象必须和list对象内部方法使用的锁对象为同一个
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
}
- 组合
//没有则添加: 通过组合实现(该方式更加健壮)
//实际上就是java监视器模式
public class ImprovedList<T> implements List<T> {
//维护一个list对象,将实现委托给list对象的方法
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;
}
//方法实现委托给list对象的方法,其他方法使用同样方式即可
public synchronized boolean add(T e) {
return list.add(e);
}
public synchronized boolean remove(Object o) {
return list.remove(o);
}
}