Java设计模式之单例模式

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

UML图

单例模式

常见应用场景
  • Windows的任务管理器就是典型的单例模式
  • windows的回收站
  • web网站的计数器
  • Spring种,每个Bean默认就是单例模式
  • SpringMvc/Struts框架,控制器也是单例模式
  • 数据库连接池
常见实现方法
主要
  • 饿汉式(线程安全,调用效率高。初始化时立即加载,天然的线程安全)
  • 懒汉式(线程安全,调用效率不高。第一次使用时加载,即可以延时加载)
其他
  • 双重检测锁式(由于编译器优化原因和JVM底层内部模式原因偶尔会出现问题,不介意使用)
  • 静态内部类式(线程安全,调用效率高。可以延时加载)
  • 枚举单例(线程安全,调用效率高,不能延时加载)
Java编码
饿汉式
/**
 * 饿汉式 单例模式
 * 线程安全,调用效率高。初始化时立即加载,天然的线程安全
 * @author H
 *
 */
public class Singleton {

	// 类初始化时,立即加载这个对象,没有延时加载的优势。加载类时,天然的线程安全
	private static Singleton singleton = new Singleton();
	
	private Singleton() {}
	
	//无需加上 synchronized
	public static Singleton getInstance() {
		return singleton;
	}
	
}

懒汉式
/**
 * 懒汉式 单例模式
 * 线程安全,第一次使用时加载,即可以延时加载
 *  资源利用率高,但是每次调用都要同步,并发效率较低
 * @author H
 *
 */
public class Singleton {

	// 类初始化时,立即加载这个对象,没有延时加载的优势。加载类时,天然的线程安全
	private static Singleton singleton ;
	
	private Singleton() {}
	//需要加上synchronized关键字,并发效率较低
	public synchronized static Singleton getInstance() {
		if(singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
	
}

双重检测锁式

由于编译器优化原因和JVM底层内部模式原因偶尔会出现问题,不介意使用

/**
 * 双重检测锁式(double check)
 * @author H
 *
 */
public class Singleton {
	private static Singleton singleton ;
	
	private Singleton() {}
	
	/**
	 * 将同步放入if内部,提高了执行的效率,不必每次获取对象都需要同步,只有第一次创建对象时需要同步
	 * 创建后就没有必要了
	 */
	public static Singleton getInstance() {
		if(singleton == null) {
			Singleton s ;
			synchronized (Singleton.class) {
				s = singleton;
				if(s == null) {
					synchronized (Singleton.class) {
						if(s == null) {
							s = new Singleton();
						}
					}
					singleton = s;
				}
			}
		}
		return singleton;
	}
}

双重检测锁式,也可以使用volatile关键字实现。

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton() {}
    public static Singleton getInstance() {
        if (singleton== null) {
            synchronized (Singleton.class) {
                if (singleton== null) {
                    singleton= new Singleton();
                }
            }
        }
        return singleton;
    } 
}
静态内部类式
/**
 * 静态内部类实现方式
 * 线程安全,调用效率高,实现延时加载
 * @author H
 *
 */
public class Singleton {
	private Singleton(){}
	
	//调用getInstance时才初始化静态内部类SingletonHolder从而创建Singleton对象
	//同饿汉式一样,天然的线程安全
	private static class SingletonHolder{
		private static Singleton singleton = new Singleton();
	}
	
	public static Singleton getInstance() {
		return SingletonHolder.singleton;
	}
}

枚举

枚举本身就是一个单例,并且在枚举中也可以声明一些行为方法。所以我们也可以直接使用枚举来实现单例模式

/**
 * 枚举
 * 线程安全,调用效率高,不能延时加载
 * @author H
 *
 */
public enum Singleton {
	INSTANCE;
}
总结

在各种单例模式的实现中,个人比较推荐内部静态类的方式。
当然,如果不需要延时加载的话,采用饿汉式的直接初始化的效果更好。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值