logo头像

Always believe youself.

并发编程-7

共享模型之不可变

不可变类的使用

不可变类设计

无状态类设计

日期转换问题

image.png

  • 用锁 sync 解决,对性能有影响
  • 不可变对象的使用,用 DateTimeFormatter 对象

不可变类的设计

String

是不可变的

final 的使用

发现该类,类中的所有属性都是 final的

  • 属性用 final 修饰保证了该属性是只读的,不能修改
  • 类用final 修饰保证了该类的方法都是不能被覆盖的,防止子类无意间破坏不可变性

保护性拷贝

string 的 char 的构造方法

image.png

image.png

进行复制操作的,这种通过创建副本对象来避免共享的手段称之为【保护性拷贝(defensive copy)】

问题点是创建太频繁。

关联出一个设计模式

享元模式(Flyweight pattern)

当需要重用数量有限的同一对象时,最小化内存的使用,可以相同值的共享。

出自 : GOF 23 种设计模式之一
属于 : 结构模式

体现

包装类

在JDK 中 Boolean,Byte,Short,Integer,Long,Character 等包装提供了valueOf 方法。

例如 Long 的 valueof 会缓存 -128 ~ 127 之间的Long 对象,在这个范围之间会重用对象,大于这个范围,才会新建 Long 对象。

初始化方法

image.png

image.png

避免对象的重复创建。

注意:
Byte,Short,Long 缓存的范围是 -128 ~ 127

Characte 缓存的范围是 0 ~ 127
Integer 的默认范围是 -128 ~ 127 ,最小值不能变,但最大的值可以通过调整虚拟机参数 - Djava.lang.Integer.intergerCache.high 来改变
Boolean缓存了True 和 False

String 串池

BigDecimal 和 BigInteger

都是不可变类 ,体现的都是享元模式,都是线程安全的。

享元模式 创建连接池

image.png

image.png

为什么 用了 cas 还需要使用 wait呢?
不使用wait 也是可以的,但是cas 是一个很短的时间的操作。
但是一般获取连接后都会是长时间的操作,一直while ,不断的cas 是非常耗CPU 资源的,这种场景是不合适的,使用wait是更合适一些。

image.png

image.png

image.png

final 原理

设置final 变量的原理

理解了 volatile 原理,再对比 final 的实现就比较简单了,

1
2
3
public class TestFinal{
final int a = 20;
}

image.png

获取 final 变量的原理

使用 final 变量是直接 把 A 变量的 10 复制到了 下面类的 栈 中。性能要高。

image.png

不使用 final 变量 是 (GETSTATIC)从另一个类中获取他的静态成员变量,走的共享内存了是从 堆中取得。 性能要低。

无状态

image.png