Immutable Object模式

Immutable Object模式 - 多线程

前言

在多线程编程中,我们常会碰到修改一个对象的值,如果在不加锁的情况下 ,就会出现值不一致的问题,那么有没有一种方式可以不通过加锁的方式也可以保证数据的一致性呢,当然有,今天介绍的不可变对象模式就可以达到这样的效果

问题

如何在多线程情况下,不重复打印出0-99的数值

可变对象模式下
  1. 首先新建一个Count对象,代码如下:
/**
 * @Author: Wang Chong 
 * @Date: 2019/9/2 22:02
 * @Version: V1.0
 */
public class Count {

    private int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }
}
  1. 新建一个CountThread线程
/**
 * @Author: Wang Chong 
 * @Date: 2019/9/2 22:14
 * @Version: V1.0
 */
public class CountThread implements Runnable {
    private Count count;

    public CountThread(Count count) {
        this.count = count;
    }

    @Override
    public void run() {
        int i = count.getI();
        System.out.println("no immutable object,current is is :" + i);
    }
}
  1. 运行程序
/**
 * @Author: Wang Chong 
 * @Date: 2019/9/2 22:17
 * @Version: V1.0
 */
public class CountMain {
    public static void main(String[] args) {
        Count count = new Count(0);
        for (int i=0; i<100;i++){
            count.setI(i);
            CountThread countThread = new CountThread(count);
            new Thread(countThread).start();
        }
    }
}
  1. 运行结果如下:
.....前面结果省略

no immutable object,current is is :93
no immutable object,current is is :93
no immutable object,current is is :94
no immutable object,current is is :96
no immutable object,current is is :85
no immutable object,current is is :97
no immutable object,current is is :98
no immutable object,current is is :91
no immutable object,current is is :99
no immutable object,current is is :99
no immutable object,current is is :99

可以发现运行结果中很多重复数字,例如93,99等

不可变对象模式
  1. 首先新建一个不可变CountImmutable对象,代码如下:
/**
 * @Author: Wang Chong
 * @Date: 2019/9/2 22:02
 * @Version: V1.0
 */
public final class CountImmutable {

    private volatile int i;

    CountImmutable(int i){
      this.i = i;
    }

    public int getI() {
        return i;
    }

    /**
     * 返回新的实例
     * @param i
     * @return
     */
    public CountImmutable set(int i){
        return new CountImmutable(i);
    }

}
  1. 新建一个CountImmutableThread线程
/**
 * @Author: Wang Chong 
 * @Date: 2019/9/2 22:14
 * @Version: V1.0
 */
public class CountImmutableThread implements Runnable {
    private CountImmutable count;

    public CountImmutableThread(CountImmutable count) {
        this.count = count;
    }

    @Override
    public void run() {
        int i = count.getI();
        System.out.println("current is :" + i);
    }
}

  1. 运行程序
/**
 * @Author: Wang Chong 
 * @Date: 2019/9/2 22:17
 * @Version: V1.0
 */
public class ImmutableDemo {
    public static void main(String[] args) {
        CountImmutable count = new CountImmutable(0);
        for (int i=0; i<100;i++){
            count = count.set(i);
            CountImmutableThread countThread = new CountImmutableThread(count);
            new Thread(countThread).start();
        }
    }
}
  1. 运行结果如下:
.....前面结果省略

current is  :69
current is  :45
current is  :89
current is  :54
current is  :57
current is  :58
current is  :39
current is  :47
current is  :51
current is  :55
current is  :91
current is  :95
current is  :99

从上面的代码,可以看到不可变对象模式下,多线程环境中不通过加锁的方式也可以保证数值的一致性

总结

不可变对象模式适用场景如下:

  • 被建模对象状态变化不频繁
  • 同时对一组相关的数据进行写操作,要保证其原子性
  • 当要用某个对象的key作为安全HashMap的Key
原文地址:https://www.cnblogs.com/pingyun/p/11451078.html