怎样实现Singleton模式才是高效和安全的?

关于Singleton的实现方式,有如下多种方式,究竟那一种是高效安全的呢? 

1、大家熟知的懒式单例

public class LazySingleton {

 private static LazySingleton instance = null;

 private static boolean flag = true;

 private LazySingleton() {
 }

 public static LazySingleton getInstance() {
  if (instance == null) {
   letMeSleep() ;
   instance = new LazySingleton();
  }
  System.out.println("instance.hashCode() : " + instance.hashCode());
  return instance;
 }

 private static void letMeSleep() {
  if (true) {
   try {
    System.out.println("let me sleep 3 sec.!");
    Thread.currentThread().sleep(3000);
    System.out.println("waking up.");
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }


 public static void main(String[] agrs) {

  //实例化两个线程
  new Thread(new Runnable() {
   public void run() {
    LazySingleton s = LazySingleton.getInstance();
   }
  }).start();
  new Thread(new Runnable() {
   public void run() {
    LazySingleton s = LazySingleton.getInstance();
   }
  }).start();
 }

}

执行结果分析:

let me sleep 3 sec.!
let me sleep 3 sec.!
waking up.
instance.hashCode() : 6413875
waking up.
instance.hashCode() : 21174459

每个线程获取的实例不一样。

 

2、好吧,用同步synchronized

     有人是这样实现的:

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

这样是否正确呢,我们还用上面的思路来进行测试:

let me sleep 3 sec.!
let me sleep 3 sec.!
waking up.
instance.hashCode() : 21174459
waking up.
instance.hashCode() : 827574

结果很不幸:(。原因在于在两个线程都执行到了if (null == instance)  里面的逻辑,然后依次执行    instance = new LazySingleton (); 这样获取两个instance实例就是正常的了。到了这里,大家都肯定知道在执行 instance = new LazySingleton () 还要判断下instance是否为空。同步块影响性能吧?想必答案是肯定的。

3、简单,安全的写法:

   

public class Singleton {

 private static Singleton instance = new Singleton();

 private Singleton() {
 }

 public static Singleton getInstance() {
  letMeSleep() ;
  System.out.println("instance.hashCode() : " + instance.hashCode());
  return instance;
 }

这样的写法简单,也安全。但是考虑到构造函数里面加载很多东西,势必延长初始化时间。

4、利用静态内部类提前实例化

public class HolderSingleton {

 private HolderSingleton(){
 }
 
 public static class SingletonHolder{
  private static HolderSingleton instance = new HolderSingleton() ;
 }
 
 public static HolderSingleton getInstance(){
  letMeSleep();
  System.out.println(SingletonHolder.instance.getClass().hashCode()) ;
  return SingletonHolder.instance ;
 }
 private static void letMeSleep() {
  if (true) {
   try {
    System.out.println("let me sleep 3 sec.!");
    Thread.currentThread().sleep(3000);
    System.out.println("waking up.");
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
 这个在JVM这一个层次有第三中山实现方式有何不一样?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值