学习中遇到 觉得有必要分享下......
单例设计模式: 保证一个类在内存中只有一个对象
构造方法私有化 内部私有化一个对象 提供一个对外访问的方法让其使用这个私有化的对象其实我本来只晓得饿汉式 懒汉式 今天突然看到一个单例设模式的实现方式 里面有DCL 静态工厂啥的我一开始不晓得DCL是啥(专业名词很蛋疼......) 后面我去找“老师” 度娘还是有的(说明这个也不是很专业 ,我有时候找一些太专业的名词度娘就抽风了 只有去找google 个人喜好百度) 原来就是在懒汉式中的为了同步安全 所在外面多加一层判断 为了提高效率吧就是这个:
~~~~~~
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
~~~~~~
顺便说下 下面这个分析 不是原创(我也没那么吊) 我是看的别人的博客写的 然后自己了解下
这个在创建对象上面 是没有问题的 他在一些情况下里面的数据会出现状态错误下面有例子
我们晓得 创建对象操作 有三个步骤 1 分配空间 new
2 复制引用入栈 dup (这个也是刚才才晓得 字节码里面的命令 高大上)
3 初始化对象
问题就出在这里 可能实例已经创建 可是还没初始化
1 new class java/lang/String 分配空间
2 dup 复制分配空间的引用入栈 这里对象就创建而且引用指向了
3 invokespecial调用初始化方法
4 astore_1 将此时栈顶的值弹出到局部变量
下面例子
public class LazySingleton {
private int someField;
private static LazySingleton instance;
private LazySingleton() {
this.someField = new Random().nextInt(100)+1;
}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized(LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance; // (6)
}
public int getSomeField() {
return this.someField;
}
}
在这个里面 instance = new LazySingleton(); 里面对象已经创建了 但是还没还没初始化 这时候someField=0
被别的线程拿到这个对象 就会出现错误 这是有可能的 这时候就出了里面数据 状态错误 因为someField在这里面是不会为0的
所以在jdk1.5 来的修复 volatile关键字的修饰(最近一直看见他 前面博客已经做了他的介绍) 他就是每次拿到都是最后修改的状态 具有修改可见性
不用改别的 只要
private volatile static LazySingleton instance;
这里就是让这个对象一直修改在主内存中 不会私有拷贝到各自线程自己的内存中 修改完了在拷贝回来 这里就算没有初始化完 因为对象还停留在没有初始化的阶段 就是另一个线程拿到 也会继续讲初始化完成
所以懒汉式的DCl 双锁检测判定 正确的写法是在
~~~~~~ private volatile static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
~~~~~~
这些事今天对于单例设计模式的进一步了解 (发现底层的了解和认知 真的对于以后的提高很有帮助 学到后面往往都是底层才能让你知道缘由)
还有 今天还看到了 几个引用
强引用 jvm宁可自己胀死也不抛弃的对象的引用
软引用 可有可无 内存不够就GC 够就不GC 这个可以加速jvm对GC的速度提升 有效防止内粗溢出
下面对于A对象 有两个引用 一个是a的强引用 一个是SoftReference对象的软引用 现在是强可及对象
A a=new A(); a有强引用
SoftReference <A> sr=new SoftReference <A>(a);
现在将a=null 现在A对象编变成了软可及对象
弱引用和软引用差不多 就是生命周期更短比软引用的被GC的可能性的
虚引用GC看到就干掉 形同虚设
浅拷贝 和 深拷贝
浅拷贝: 两个引用共享一个对象实例 修改一个都变
深拷贝: 一个对象被新建一个 内容一样 但是都占用空间内存 所以不是同一个 修改一个另一个不变
|
|