饿汉、懒汉之单例模式!!

单例模式是什么?为什么需要单例模式

单例模式顾名思义,就是在整个运行时域,一个类只有一个实例对象。
为什么需要单例模式,因为有的类实例对象创建与销毁资源消耗不大,比如String,有的类庞大复杂,如果频繁创建销毁会造成不必要的浪费。
比如创建数据库连接对象Connection con,可以使用单例模式,避免重复创建销毁。

饿汉模式

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

这种模式是在类加载的同时就进行实例化了,避免了多线程的同步问题。当然缺点也是有的,因为类加载时就实例化了,没有达到Lazy Loading (懒加载) 的效果,如果该实例没被使用,内存就浪费了。

懒汉模式

懒汉模式顾名思义就是在需要这个类的时候在进行实例化,而不是在加载就实例化
一个最基本的懒汉模式:

public class Singleton {
	private static Singleton instance;
	private Singleton() {}
	public static Singleton getInstance() {
		if (instance == null) {//此处线程不安全
			instance = new Singleton();
		}
		return instance;
	}
}

这种写法是线程不安全的,比如AB两个线程同时,在同时进行判空,那么会实例化多次
如何解决呢?可以打上synchronized,变成如下

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

打上synchronzed后只有一个线程可以进入getinstance方法。随之而来的问题就是,我们需要在构建对象的时候进行同步加锁操作,而此写法在每次获取对象的时候都加上锁了,对性能影响很大。所以不可取

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

这种情况下在当前A线程获得锁的线程后可能有其他如B线程也在等待进入这个Class锁,A线程获取锁后创建实例,然后释放锁,之后等待池中的B线程获得锁,然后就会产生创建两个对象的错误情况

public class Singleton {
	private static Singleton instance;
	private Singleton() {}
	public static Singleton getInstance() {
		if (instance == null) {
			synchronized(Singleton.class);
			if (singleton == null) {
				instance = new Singleton();//线程不安全
			}
		}
		return instance;
	}
}

因为hanpens-before原则,实例化对象有三部:分配内存、初始化对象、将对象指向内存。在执行的时候为了效率会进行指令重排,多线程下会乱套。

public class Singleton {
	private volatile static Singleton instance;//加入volatile
	private Singleton() {}
	public static Singleton getInstance() {
		if (instance == null) {
			synchronized(Singleton.class);
			if (singleton == null) {
				instance = new Singleton();
			}
		}
		return instance;
	}
}

这样就完美了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值