Immutability模式
Immutability模式:对象一旦被创建之后,状态就不再发生变化
不可变类
- 将一个类所有的属性都设置成final,并且只允许存在只读方法
- 将类也设置成final的,因为子类可以重写父类的方法,有可能改变不可变性
包装类
- String、Integer、Long和Double等基础类型的包装类都具备不可变性
- 这些对象的线程安全都是靠不可变性来保证的
- 严格遵守:_类和属性都是final的,所有方法均是只读的_
- 如果具备不可变性的类,需要提供修改的功能,那会创建一个新的不可变对象
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | private final char value[];
 public String replace(char oldChar, char newChar) {
 if (oldChar != newChar) {
 int len = value.length;
 int i = -1;
 char[] val = value;
 
 while (++i < len) {
 if (val[i] == oldChar) {
 break;
 }
 }
 if (i < len) {
 char buf[] = new char[len];
 for (int j = 0; j < i; j++) {
 buf[j] = val[j];
 }
 while (i < len) {
 char c = val[i];
 buf[i] = (c == oldChar) ? newChar : c;
 i++;
 }
 
 return new String(buf, true);
 }
 }
 return this;
 }
 
 | 
享元模式
- 享元模式本质上是一个_对象池_
- Long内部维护了一个静态的对象池,仅缓存[-128,127](利用率最高)之间的数字
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | public static Long valueOf(long l) {final int offset = 128;
 if (l >= -128 && l <= 127) {
 return LongCache.cache[(int)l + offset];
 }
 return new Long(l);
 }
 
 
 private static class LongCache {
 private LongCache(){}
 
 static final Long cache[] = new Long[-(-128) + 127 + 1];
 
 static {
 for(int i = 0; i < cache.length; i++)
 cache[i] = new Long(i - 128);
 }
 }
 
 | 
锁
基本上所有基础类型的包装类都不适合做锁,因为它们内部用到了享元模式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | class A {
 private Long al = Long.valueOf(1);
 
 public void set() {
 synchronized (al) {
 }
 }
 }
 
 class B {
 private Long bl = Long.valueOf(1);
 
 public void set() {
 synchronized (bl) {
 }
 }
 }
 
 | 
注意事项
不可变性的边界
- 对象的所有属性都是final,也并不能保证不可变性
- 需要明确不可变性的边界,是否要求属性对象也具有不可变性
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | @Dataclass Foo {
 private int age = 0;
 private String name = "abc";
 }
 
 final class Bar {
 private final Foo foo = new Foo();
 
 public void setAge(int age) {
 
 foo.setAge(age);
 }
 }
 
 | 
正确发布
不可变对象是线程安全的,但并不意味着引用这些不可变对象的对象也是线程安全的
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | @Data
 final class C {
 final int age = 0;
 final String name = "abc";
 }
 
 
 class D {
 private C c;
 
 
 
 
 public void setC(C c) {
 this.c = c;
 }
 }
 
 | 
无状态
- 具备不可变性的对象,只有一种状态,这个状态由对象内部所有的不可变属性共同决定的
- 还有一种更简单的不可变对象,即无状态,无状态对象内部没有属性,只有方法
- 无状态的核心优势是性能
- 在多线程领域,无状态对象没有线程安全问题,无需同步处理
- 在分布式领域,无状态服务可以无限地水平扩展
 
参考资料
Java并发编程实战