单例模式详细总结—创建型模式—设计模式1

0. 单例模式

  • 定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
  • 要素:私有构造方法;指向自己实例的静态引用;以自己实例为返回值的静态共有方法;
  • 分类:饿汉式(类加载时就实例化);懒汉式(调用时实例化);
  • 优点:节省内存空间;避免频繁的创建和销毁,提高性能;避免对共享资源的多重占用;可以全局访问;
  • 适用场景:需要频繁实例化并销毁的对象;创建对象开销大的对象;有状态的工具对象;频繁访问数据库或文件的对象;
  • 具体场景:定时器;网页访问人数统计;电脑打印程序;生产唯一序列号;WEB中的计数器;数据库连接;
  • 注意:除非认为地断开单例中静态引用到单例对象的关联否则JVM不会回收单例对象;使用反射机制会破坏单例机制,可以通过在构造函数中进行判断来避免或者使用枚举类;

总的来看:推荐使用静态内部类实现方式、双检锁实现方式,如果有特殊需求严格保证单例不被破坏需要使用枚举方式。

1. 一些实现方式

懒汉式,线程不安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

懒汉式,线程安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    // 通过加锁的方式避免多个线程同时创建多个对象
    // 这种方式有缺点:其实只需要在第一次创建的时候加锁,如果实例存在后面就不需要加锁
    // 所以可以通过双检锁的方式进行改进
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
} 

双检锁,线程安全

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
    	// 只有当实例为空的时候才进行加锁
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}  

饿汉式,线程不安全

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}  

静态内部类,线程安全

// 该方式一方面达到的双检锁的效果
// 另一方面实现了延迟加载,是比较理想的实现方式
public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}   

枚举方式,线程安全,避免反射破坏

// 虽然可以在前面方法的构造方法中加入一些判断条件,例如实例如果存在,再次调用构造函数就报错
// 但是针对一些复杂的场景还是很难真正保证单例的,而枚举可以很好的保证
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值