单例模式的五种实现

单例模式:类只会被实例化一次,每次都是调用同一个对象。

在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。

单例模式有 3 个特点:

  • 单例类只有一个实例对象;
  • 该单例对象必须由单例类自行创建;
  • 单例类对外提供一个访问该单例的全局访问点;
1、懒汉式(效率太低)
/**
 * 通过懒汉模式实现单例模式,synchronized同步会大大降低效率
 * @author HP
 *
 */
public class SingletonLanHan {

	private static SingletonLanHan instance;
	
	private SingletonLanHan(){
		System.out.println("我是懒汉");
	}
	
	//如果不加synchronized就会造成多线程中的不安全
	public synchronized static SingletonLanHan getInstance(){
		if(instance == null){
			instance = new SingletonLanHan();
		}
		return instance;
	}
}
2、饿汉式(基于classloader机制,但不能懒加载)
/**
 * 饿汉模式实现单例模式,不能实现懒加载
 * 在类加载阶段就进行了实例化
 * @author HP
 *
 */
public class SingletonEHan {

	private static SingletonEHan instance = new SingletonEHan();
	
	private SingletonEHan(){
		System.out.println("饿汉创建成功");
	}
	
	//静态工厂模式实例化对象
	public static SingletonEHan getInstance(){
		return instance;
	}
}
3、静态内部类实现
/**
 * 通过静态内部类实现单例模式,可以实现懒加载
 * @author HP
 *
 */
public class SingletonInnerClass {

	private static class SingletonHolder{
		private static final SingletonInnerClass instance = new SingletonInnerClass();
	}
	
	public SingletonInnerClass(){
		System.out.println("我是通过静态内部类实现");
	}
	
	public static SingletonInnerClass getInstance(){
		return SingletonHolder.instance;
	}
}
4、枚举类实现(最佳方法)
/**
 * 通过枚举实现的单例模式
 * 不仅能实现多线程的同步
 * 还能防止反序列化创建不同的实例
 * 目前认为的最佳实现单例模式的方法
 * 枚举类内部实现了public static final
 * 并默认调用了私有无参构造器
 * @author HP
 *
 */
public enum SingtonMeiJu {

	INSTANCE;
	
	private SingtonMeiJu(){
		System.out.println("我是通过枚举实现的");
	}
}
5、双重检查锁(DCL)
/**
 * 双重检查锁实现单例模式
 * @author HP
 *
 */
public class SingtonDCL {

	//使用volatile防止指令重排序
	private volatile static SingtonDCL instance;
	
	private SingtonDCL(){
		System.out.println("通过双重校验锁实现单例模式");
	}
	
	public static SingtonDCL getInstance(){
		if(instance == null){
			//使用synchronized同步方法块,可以提升性能
			synchronized(SingtonDCL.class){
				/**
				 * 第二次检查的目的是为了防止两个线程都经过了第一道检查
				 * 然后一个线程抢到锁后进入了代码块,创建了实例,然后释放锁
				 * 第二个线程又抢到锁进入了代码块
				 * 如果没有第二次检查,第二个线程就会创建第二个实例
				 */
				if(instance == null){
					instance = new SingtonDCL();
				}
			}
		}
		return instance;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值