概述
创建型模式-1
1.单例模式
1.1 介绍
单例模式 singleton pattern :用来保证一个对象只会创建一个实例是最常用的设计模式,它具有易于理解,使用简便.但有时候在过度的使用会有适得其反的效果; 就比如单例懒加载一个大对象,在使用的时候在加载就会有明显的延迟;
1.2 单例模式V1
下面是最简单的单例模式
public class SingletonV1 {
public static SingletonV1 singleton;
private SingletonV1(){}
public static SingletonV1 getInstance(){
if(singleton ==null){
singleton = new SingletonV1();
}
return singleton;
}
}
这样的单例模式在单线程的环境下面是没有问题的,当运行在多线的环境下面就是两个线程会同事的调用getInstance() 方法的时候,第一个线程正在实例化对象还没有完全的创建成功,又有一个线程在执行有去实例化一次
1.3 单例模式V2
class SingletonV2 {
public static SingletonV2 singleton;
private SingletonV2(){}
public static synchronized SingletonV2 getInstance(){
if(singleton ==null){
singleton = new SingletonV2();
}
return singleton;
}
}
1.4 单例模式V3
class SingletonV3 {
public static SingletonV3 singleton;
private SingletonV3(){}
public static SingletonV3 getInstance(){
synchronized (SingletonV3.class){
if(singleton ==null){
singleton = new SingletonV3();
}
return singleton;
}
}
}
上面两个版本是一样的都使用了synchronized 的关键字来是的方法同步,只有一个线程可以访问,这样基于导致了效率下降
1.5 双重校验机制的同步锁单例模式V4
class SingletonV4 {
public static SingletonV4 singleton;
private SingletonV4() {
}
public static SingletonV4 getInstance() {
if (singleton == null) {
synchronized (SingletonV4.class) {
if (singleton == null) {
singleton = new SingletonV4();
}
}
}
return singleton;
}
}
1.6 voletile 单例模式V5
class SingletonV4 {
public static volatile SingletonV4 singleton;
private SingletonV4() {
}
public static SingletonV4 getInstance() {
if (singleton == null) {
synchronized (SingletonV4.class) {
if (singleton == null) {
singleton = new SingletonV4();//这一步
}
}
}
return singleton;
}
}
修复V4 版本可能出现的指令排序 因为在上面的哪一步 可以分为以下几个步骤
a). 分配内存 b). 初始化对象 c).对象引用给变量
上面的步骤是singleton 对象正常的初始化步骤 ,但是如果出现了指令重排序的问题,比如b和c 重排序了 ,那么并发环境下别的线程可能获取到的就是未初始化完全的对象,进而导致一些无法预料的错误;
1.7 无锁线程安全的单例模式V6
class SingletonV5 {
public static SingletonV5 singleton = new SingletonV5();
private SingletonV5() {
System.out.println();
}
public static SingletonV5 getInstance() {
return singleton;
}
}
在类加载的时候就预先直接加载了实例 属于提前加载
1.8 内部类的单例模式V7
class SingletonV6 {
private SingletonV6() {
System.out.println("SingletonV6");
}
public static SingletonV6 getInstance() {
return Assist.singletonV6;
}
static class Assist{
public static SingletonV6 singletonV6 = new SingletonV6();
}
}
外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化singletonV6,故而不占内存。即当SingletonV6第一次被加载时,并不需要去加载Assist,只有当getInstance()方法第一次被调用时,才会去初始化singletonV6,第一次调用getInstance()方法会导致虚拟机加载Assist类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。
不管有多少线程同时访问getInstance () ,但是里面的Assist 只会加载一次 也就是实例singletonV6 只会加载一次
缺点:都是静态的无法传递初始化时需要的参数
1.9 枚举单例V8
public enum SingleTon{
INSTANCE;
public void method(){
//TODO
}
}
虚拟机层面保证的单例模式
2. 角色
最后
以上就是淡然溪流为你收集整理的设计模式-创建型模式-单例模式-1创建型模式-1的全部内容,希望文章能够帮你解决设计模式-创建型模式-单例模式-1创建型模式-1所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复