并发编程-7
共享模型之不可变
不可变类的使用
不可变类设计
无状态类设计
日期转换问题
- 用锁 sync 解决,对性能有影响
- 不可变对象的使用,用 DateTimeFormatter 对象
不可变类的设计
String
是不可变的
final 的使用
发现该类,类中的所有属性都是 final的
- 属性用 final 修饰保证了该属性是只读的,不能修改
- 类用final 修饰保证了该类的方法都是不能被覆盖的,防止子类无意间破坏不可变性
保护性拷贝
string 的 char 的构造方法
进行复制操作的,这种通过创建副本对象来避免共享的手段称之为【保护性拷贝(defensive copy)】
问题点是创建太频繁。
关联出一个设计模式
享元模式(Flyweight pattern)
当需要重用数量有限的同一对象时,最小化内存的使用,可以相同值的共享。
出自 : GOF 23 种设计模式之一
属于 : 结构模式
体现
包装类
在JDK 中 Boolean,Byte,Short,Integer,Long,Character 等包装提供了valueOf 方法。
例如 Long 的 valueof 会缓存 -128 ~ 127 之间的Long 对象,在这个范围之间会重用对象,大于这个范围,才会新建 Long 对象。
初始化方法
避免对象的重复创建。
注意:
Byte,Short,Long 缓存的范围是 -128 ~ 127
Characte 缓存的范围是 0 ~ 127
Integer 的默认范围是 -128 ~ 127 ,最小值不能变,但最大的值可以通过调整虚拟机参数 - Djava.lang.Integer.intergerCache.high 来改变
Boolean缓存了True 和 False
String 串池
BigDecimal 和 BigInteger
都是不可变类 ,体现的都是享元模式,都是线程安全的。
享元模式 创建连接池
为什么 用了 cas 还需要使用 wait呢?
不使用wait 也是可以的,但是cas 是一个很短的时间的操作。
但是一般获取连接后都会是长时间的操作,一直while ,不断的cas 是非常耗CPU 资源的,这种场景是不合适的,使用wait是更合适一些。
final 原理
设置final 变量的原理
理解了 volatile 原理,再对比 final 的实现就比较简单了,
1 | public class TestFinal{ |
获取 final 变量的原理
使用 final 变量是直接 把 A 变量的 10 复制到了 下面类的 栈 中。性能要高。
不使用 final 变量 是 (GETSTATIC)从另一个类中获取他的静态成员变量,走的共享内存了是从 堆中取得。 性能要低。