你真的会单例吗?单例的八种写法

说起单例设计模式因该很多人都不陌生,按理说只有接触过java的都应该知道这个设计模式,但是你真的会写吗?还是说只会懒汉式和饿汉式?其实日常工作中随便掌握一种就已经可以了,但是我们身为java程序员应该不断的学习,即使用不到但是也要来了解以下,接下来我就来给你们写单例的八种写法,其中只有四种是能有并且没有问题的,其他的都有问题

写法一:传统的饿汉式

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

public class Main{
	public static void main(String[] args){
		Singleton01 instance = Singleton01.getInstance();
	}
}

这种就是传统的饿汉式,相信你们并不陌生,这种其实已经很好了,在工作中就写这种也没有任何问题,但是会有些人觉得这个太浪费资源,因为只要去加载这个类,那么这个实例就会创建

写法二:有问题的写法,懒汉式

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

public class Main{
	public static void main(String[] args){
		Singleton02 instance = Singleton02.getInstance();
	}
}

这种写法在多线程的情况下不能保证只有一个实例,所以这是有问题的

写法三:加锁,懒汉式

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

public class Main{
	public static void main(String[] args){
		Singleton03 instance = Singleton03.getInstance();
	}
}

这种写法每次去拿对象的时候都会加锁,我们都知道加锁会导致效率变慢

写法四:判断加锁,懒汉式

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

public class Main{
	public static void main(String[] args){
		Singleton04 instance = Singleton04.getInstance();
	}
}

这种写法虽然对比上面那中效率高了些,但是在多线程的响应下,他还是不能保证只有一个实例

写法五:双重判断加锁,懒汉式

class Singleton05{

	private static volatile Singleton05 instance;

	private Singleton05(){}

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


}

这种写法也很常见,这样只要有一个线程将这个实例创建出来了,就不会执行下面的加锁的那段代码,所以效率还是可以的,只有第一次拿的时候会稍微慢一点,因为第一次要创建对象

写法六:静态内部类的方法

public class Singleton06 {

	private static class SingletonInstance{
		
		private static final Singleton06 INSTANCE = new Singleton06();
		
	}
	
	
	private Singleton06() {}
	
	public static  Singleton06 getInstance() {
		return SingletonInstance.INSTANCE;
		
	}
	
}


这种方式已经够很完美了,通过内部类的方式来保证这个单例,这种写法可能看到过的人就比较少了

写法7:枚举单例


public enum Singleton07 {

	INSTANCE;
	
	
	
}


这种才是最最最完美的,也是最简单的,下面还有一种,这种应该写在第二种的,但是由于我个人给忘了,所以就写到最下面吧,

写法八:通过静态代码块,饿汉式


public class Singleton08 {

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



这种跟第一种是一样的,也就没有必要说了,看到这里你才是真正的了解这个单例模式了。不加volatile可能在指令重排的时候出问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值