java设计模式-单例模式
什么是单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,又称:原子模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式的优点
- 减少了内存的开销。由于内存中只有一个实例,就减少了对象的创建、销毁的开销,而且目前对于对象创建、销毁是没办法进行性能优化的。
- 减少了性能上面的开销。单例模式可以在开始的时候就初始化相关操作,并且保留在内存中,这样就减少了系统运行的性能开销,比如配置的读取能,可以减少io上面频繁的操作。
- 可以共享资源。我们可以把单例模式设置成系统的全局访问点,可以优化和共享资源的访问。比如,加密工具类
单例模式的缺点
没有一个事物是完美的,拥有那么多优点的单例模式又有哪些缺点呢?
- 扩展能力低。由于接口和抽象类是不能被初始化的,所以单例模式一般都是对象类。在一定情况下,单例模式可以被继承和实现接口。但是能被做单例的都不会说接口
- 违反了单一职责原则。是否单例是根据环境来决定,而不是根据职责来控制,单例会把业务逻辑混合在里面。
单例模式的应用场景
- 要求只有单一对象,出现多个对象会有问题,比如,唯一序列号生成器。
- 资源共享访问点。可以减少性能的开销
- 需要大量静态变量或方法(工具类)
单例模式的线程安全
由于内存中只有一个对象,那么多方都会调用该对象,就很容易出现线程安全问题,一般方法内创建的变量不会有问题,核心是单例本身和单例的全局变量。
public class UnsafeSingleton {
private static UnsafeSingleton unsafeSingleton;
/**
* 私有构造器,限制外部不能实例
*/
private UnsafeSingleton() {
}
public static UnsafeSingleton getInstance() {
if (unsafeSingleton == null) {
unsafeSingleton = new UnsafeSingleton();
}
return unsafeSingleton;
}
}
[代码链接]github.com/fightcrap/j…)
代码解析:这是一个不安全的单例模式,属于懒加载模式的单例。为嘛说这个是不安全的呢?在多线程环境中,线程A来调用getInstance方法,发现没有实例化,则会进入判断括号体中,进行初始化,我们知道,对象实例化的时候,会出现重排序问题,会先分配空间,但是没有赋值,则这个时候线程B进来,发现已经不会为null了,就返回了,所以线程B会出现空指针异常(这是一种情况);(情况二:)A刚刚进入判断体,线程B也刚刚进来,则会B也进入了判断体,就有两个线程进行实例化的问题。所以这是一个不安全的单例 安全的单例写法:
public class SafeSingleton {
/**
* 加上volatile避免重排序问题
*/
private static volatile SafeSingleton safeSingleton;
private SafeSingleton(){
}
public static SafeSingleton getInstance(){
//双重锁判断,避免了线程重进入安全问题
if(safeSingleton==null){
synchronized (SafeSingleton.class){
if(safeSingleton==null){
safeSingleton=new SafeSingleton();
}
}
}
return safeSingleton;
}
}
多形式的单例模式
- 饿汉式
public class HungrySingleton { private static HungrySingleton hungrySingleton=new HungrySingleton(); private HungrySingleton(){ } /** * 饿汉模式会优先初始化对象。所以是线程安全的 * @return */ public static HungrySingleton getInstance(){ if(hungrySingleton==null){ hungrySingleton=new HungrySingleton(); } return hungrySingleton; } } - 懒汉模式
public class UnsafeSingleton { private static UnsafeSingleton unsafeSingleton; /** * 私有构造器,限制外部不能实例 */ private UnsafeSingleton() { } public static UnsafeSingleton getInstance() { if (unsafeSingleton == null) { unsafeSingleton = new UnsafeSingleton(); } return unsafeSingleton; } } - 懒汉模式(线程安全版)
public class SafeLazySingleton { private static SafeLazySingleton safeLazySingleton; private SafeLazySingleton(){ } /** * 利用synchronized 锁定类对象,锁的力度更大,使得锁的限制在调用前。确保逻辑走完,所以线程安全 * @return */ public static synchronized SafeLazySingleton getInstance(){ if(safeLazySingleton==null){ safeLazySingleton=new SafeLazySingleton(); } return safeLazySingleton; } } - 懒汉模式(双重锁判断)
public class UnsafeSingleton { private static UnsafeSingleton unsafeSingleton; /** * 私有构造器,限制外部不能实例 */ private UnsafeSingleton() { } public static UnsafeSingleton getInstance() { if (unsafeSingleton == null) { unsafeSingleton = new UnsafeSingleton(); } return unsafeSingleton; } } - 静态内部类单例模式
public class SingletonDesign { /** * 利用静态内部类加载的形式,限制外部访问,并且初始化本身,达到单例的目的 */ private static class Singleton{ public static final SingletonDesign singletonDesign=new SingletonDesign(); } private SingletonDesign(){ } public static SingletonDesign getInstance(){ return Singleton.singletonDesign; } } - 枚举单例
public enum Singleton { SINGLETON; }