单例模式的简单使用

本文深入探讨了单例模式的三种实现方式——饿汉式、懒汉式和双重检查锁定,分析了各自的优缺点,并重点讲解了如何解决多线程安全问题。

作用:控制一个类型有且只有一个对象
一、创建方法(饿汉式)
1.私有化构造方法,防止类体之外的别人创建对象
2.创建一个静态的,私有的属于本类类型的对象
3.创建一个公共的返回本类类型对象的方法

缺点:
1):实例在类初始化一开始就被创建了,哪怕后来根本没有使用它
2):如果实例的创建时依赖于外部的参数/文件的话,这种方式就不适用了
代码示例:


class Student{
	private String name;
	private int age;

	public void setName(String name){
		this.name = name;
	}

	public String getName(){
		return name;
	}

	public void setAge(int age){
		this.age = age;
	}

	public int getAge(){
		return age;
	}
	//要求学生类实现封装和单例

	//单例:
	//私有化构造方法
	private  Student(String name, int age)
	{
	   this.name=name;
	   this.age=age;
	}
	//创建一个静态的私有的 返回本类类型的对象
	private  static Student stu=new Student("Tom",18); 
	//创建一个公共方法 返回本类对象
	public static Student getStu(){
                return stu; 
}

二.懒汉式

 class  Sun(){//懒汉式
        private  Sun():
        private static  Sun sun;
        public static Sun getSun(){
            if(sun==null) {
                sun=new Sun();
            }
            return sun;
    }
    } 
  缺点:多线程环境下不安全

三.对懒汉式的改进 加锁

//为了防止线程并发问题首先想到对方法进行加锁即

class SunPlus{
   private SunPlus();
   private static SunPlus sun;
   public synchronized static SunPlus getSun(){
     if(sun==null){
      sun =new Sun();
     }
     return sun;
 }
}

缺点:整个方法都被synchronized所包围,因此增加了同步开销,降低了程序执行效率。

再改进

 //对懒汉式的改进
    class SunPlus(){//双重检验锁
        private SunPlus();
        private static SunPlus sun;
        public   static SunPlus  getSun(){
            if(sun==null){
                Synchorized(SunPlus.class){
                    if(sun==null){
                    sun=new Sun();
                    }
                }
            }
            return sun;
        }        
    }
使用两次判断的原因:有可能多个线程同时进入第一个 if 判断,如果在同步块中不再次判断的话,有可能生成多个实例

由于JVM指令重排序的优化,在instance = new Singleton();仍有可能生成多个实例

在JVM指令优化时,instance = new Singleton();并不是一个原子操作,而是3个步骤:
1. 为instance分配内存
2. 调用 Singleton构造函数初始化成员变量
3. 将instance对象指向分配的内存空间 (instance非null)

再改进 用volatile修饰 防止指令重排序

    class SunPlus(){//双重检验锁
        private SunPlus();
        private volatile static SunPlus sun;
        public   static SunPlus  getSun(){
            if(sun==null){
                Synchorized(SunPlus.class){
                    if(sun==null){
                    sun=new Sun();
                    }
                }
            }
            return sun;
        }        
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值