Java多线程设计模式---不可变对象模式

1. 运用背景

  • 被建模对象的状态变化不频繁。
  • 避免显式锁等并发访问控制的开销和问题。
  • 使用某个对象作为安全的HashMap的key。

2. 解决方案

  • 通过使用对外可见的状态不可变的对象(Immutable Object),使得被共享对象“天生”具有线程安全性,而无需额外地同步访问控制。
  • 保证了数据一致性,又避免了同步访问控制所带来的额外开销和问题,也简化了编程。

3. 状态不可变对象:

  • 对象一经创建,其对外可见的状态就保持不变,比如String和Integer。
  • 代码示例:
public final class Location
{
    public final double x;
    public final double y;
    
    public Location(double x, double y)
    {
        this.x = x;
        this.y = y;
    }
}

一个严格意义上的不可变对象要满足以下所有条件
(1) 类本身使用final 修饰;
(2) 所有字段都用final修饰;
(3) 在对象创建过程中,this关键字没有泄露给其他类;
(4) 任何字段,若其引用了其他状态可变对象(如集合、数组等),则这些字段必须是private修饰的,并且这些字段值不能对外泄露。

4. 架构

Immutable Object 模式将现实世界中状态可变的实体建模为状态不可变对象,并通过创建不同的状态不可变对象来反映现实世界实体的状态变更。

主要参与者
  • ImmutableObject: 负责存储一组不可变状态(如上文的Location),该参与者不对外暴露任何可以修改其状态的方法。
  • Manipulator: 负责维护ImmytableObject 所建模的现实世界实体状态的变更。当相应的现实实体状态变更时,负责生产新的ImmutableObject 对象,以反映新的状态。

5. Java 标准库实例

  • JDK 1.5 中引入的类java.util.concurrent.CopyOnWriteArrayList 应用了Immutable Object 模式,使得对CopyOnWriteArrayList 实例进行遍历时不用加锁也能保证线程安全。
  • CopyOnWriteArrayList 是专门针对遍历操作的频率比添加和删除操作更加频繁的场景设计的。
  • CopyOnWriteArrayList 的源码骨架:
public class CopyOnWriteArrayList
    implements List, RandomAccess, Cloneable, java.io.Serializable {

    //省略其他代码

    /** The array, accessed only via getArray/setArray. */
    private transient volatile Object[] array;

    /**
     * Gets the array.  Non-private so as to also be accessible
     * from CopyOnWriteArraySet class.
     */
    final Object[] getArray() {
        return array;
    }

    /**
     * Sets the array.
     */
    final void setArray(Object[] a) {
        array = a;
    }

    //省略其他代码
  
    /**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * 

The returned iterator provides a snapshot of the state of the list * when the iterator was constructed. No synchronization is needed while * traversing the iterator. The iterator does NOT support the * {@code remove} method. * * @return an iterator over the elements in this list in proper sequence */ public Iterator iterator() { return new COWIterator(getArray(), 0); } /** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }

你可能感兴趣的:(Java多线程设计模式---不可变对象模式)