Java Singleton Design Pattern (单例模式 SE7 Gold)

singleton design pattern offer 2 things:
one and only one instance of the class, and a global single point of access to that object

下面的例子用一个private的构造函数阻止了instance的生成,所以不能用new生成一个新的instance,只能用getInstance()来得到instance,可以看到生成instance后把它赋给static成员myInstance,所以可以always return the same object:

public class Logger{
   //declare the constructor private to prevent clients from instantiating..
   private Logger(){}
   private static Logger myInstance;
   //the static method to get instance..
   public static Logger getInstance() {
   	  if (myInstance == null) {
   	  	 myInstance = new Logger();
   	  }
   	  return myInstance;
   }
}

但是上面的实现有什么不妥之处?上面的实现对于单线程是有效的,但是对于多线程,仍然可以得到很多的object,违背了singleton的理念

对于多线程的singleton,看下面的例子
getInstance()方法中用到了synchronized修饰,每次只能一个线程访问,确保每次只能生成一个instance

public class Logger{
   //declare the constructor private to prevent clients from instantiating..
   private Logger(){}
   private static Logger myInstance;
   //the static method to get instance..
   public static synchronized Logger getInstance() {  //added..
   	  if (myInstance == null) {
   	  	 myInstance = new Logger();
   	  }
   	  return myInstance;
   }
}

上面的实现有什么问题?poor performance。
其实本意是在第一次生成instance的时候用synchronized进行限制,但是整个method都变成了synchronized,导致多线程每次调用getInstance(), 这个地方会变成performance bottleneck

那么考虑把synchronized移到第一次生成instance的地方,是否就完美解决上述问题

public class Logger{
   //declare the constructor private to prevent clients from instantiating..
   private Logger(){}
   private static Logger myInstance;
   //the static method to get instance..
   public static Logger getInstance() {
   	  if (myInstance == null) {
   	     synchronized (Logger.class) {   //added..
   	  	 	myInstance = new Logger();
   	  	 }
   	  }
   	  return myInstance;
   }
}

仍然会有问题,如果两个线程同时第一次生成instance,同时判断到了myInstance== null
synchronized无法保护上面的判断,所以仍然会生成两个object

因此解决方法是实行双重检查myInstance== null, 但是这种方法不被推荐,因为erroneous out of order writes allowed by java memory model problem的关系, 虽然memory model已经修复了这个问题

public class Logger{
   //declare the constructor private to prevent clients from instantiating..
   private Logger(){}
   private static Logger myInstance;
   //the static method to get instance..
   public static Logger getInstance() {
   	  if (myInstance == null) {
   	     synchronized (Logger.class) {
   	        if (myInstance == null) {   //added..
   	  	 		myInstance = new Logger();
   	  	 	}
   	  	 }
   	  }
   	  return myInstance;
   }
}

下面用另一种内部类的方法实现singleton
因为内部类are not loaded until they are referenced
仍然用private限制了构造函数

public class Logger{
   //declare the constructor private to prevent clients from instantiating..
   private Logger(){}
   private static Logger myInstance;
   public static class LoggerHolder {
   	  public static Logger logger = new Logger();
   }
   public static Logger getInstance() {
   	  return LoggerHolder.logger;
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值