不可变对象设计模式
每次修改共享数据对象都会生成新的共享数据对象,使用final修饰,实现无锁。例如String就是不可变对象。
实例
/**
* 使用不可变对象设计 int值累加
*/
// final 类不能被继承
public final class IntegerAccumulator {
// 不可变对象
private final int init;
// 两种构造器
public IntegerAccumulator(int init) {
this.init = init;
}
public IntegerAccumulator(IntegerAccumulator accumulator,int init){
this.init = accumulator.getValue()+init;
}
// 累加方法重新返回一个对象 java8的函数式 也是返回一个新的对象
public IntegerAccumulator add(int i){
return new IntegerAccumulator(this,i);
}
private int getValue() {
return this.init;
}
// 测试多线程累加
public static void main(String[] args) {
IntegerAccumulator accumulator = new IntegerAccumulator(0);
IntStream.range(0,4).forEach(i-> new Thread(() -> {
int inc = 0;
while (true){
int oldValue = accumulator.getValue();
int result = accumulator.add(inc).getValue();
System.out.println(currentThread().getName()+" "+oldValue+" + "+inc+" = "+result);
if(inc+oldValue != result) {
System.out.println("线程之间冲突,导致不一致");
}
inc++;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
},"测试线程"+i).start());
}
}
总结
上述代码使用的是int类型来测试,final修饰的只能保证引用不变,所以当不可变对象为list等集合对象时就不能保证每次修改集合中的对象会重新生成集合对象。这种情况就要通过设置集合的不能变属性或者自己生成一个新集合返回。
final class listAccumulator{
private final List<String> list;
listAccumulator(List<String> list) {
this.list = list;
}
public List<String> getList() {
return Collections.unmodifiableList(this.list);
}
}