作用:控制一个类型有且只有一个对象
一、创建方法(饿汉式)
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;
}
}
本文深入探讨了单例模式的三种实现方式——饿汉式、懒汉式和双重检查锁定,分析了各自的优缺点,并重点讲解了如何解决多线程安全问题。
872

被折叠的 条评论
为什么被折叠?



