单例

一、Java中的单例:

特点:

1. 单例类只有一个实例

2. 单例类必须自己创建自己唯一实例

3. 单例类必须给所有其他对象提供这一实例

二、两种模式:

1.懒汉式单例<线程不安全>

在类加载时,不创建实例,运行调用时创建。类加载快,在运行时获取对象速度慢

示例:

复制代码
public class Singleton {
    private static Singleton uniqueInstance = null;
 
    private Singleton() {
      
    }
 
    public static Singleton getInstance() {
       if (uniqueInstance == null) {
           uniqueInstance = new Singleton();
       }
       return uniqueInstance;
    }
复制代码

2.饿汉式单例<线程安全>

在类加载的时候,就完成初始化。所以类加载慢,但是在运行时获取对象快

示例:

复制代码
    //饿汉式单例类.在类初始化时,已经自行实例化 

     public class Singleton1 {

      //私有的默认构造子
      private Singleton1() {}

      //已经自行实例化 
      private static final Singleton1 single = new Singleton1();

      //静态工厂方法 
      public static Singleton1 getInstance() {

          return single;
     }
 }
复制代码

三、如何保证多线程下的单例:

1.同步锁<主要是通过使用synchronized来加互斥锁进行同步控制。>

复制代码
public class LazySingleton {

private static LazySingleton instance = null;   

private LazySingleton(){}   


public static synchronized LazySingleton getInstance(){     

   if(instance == null){   
         instance = new LazySingleton();   
     }     
   return instance;   
 }
}
复制代码

双重校验锁

      所谓“双重检查加锁”机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查,进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

  “双重检查加锁”机制的实现会使用关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

复制代码
    private volatile static Singleton instance = null;  
    private Singleton(){}  
    public static Singleton getInstance(){  
   
   //先检查实例是否存在,如果不存在才进入下面的同步块 
   
    if(instance == null){           

  //同步块,线程安全的创建实例     

       synchronized (Singleton.class) {       
   
      //再次检查实例是否存在,如果不存在才真正的创建实例         
       if(instance == null){                  
       instance = new Singleton();      
          }         
   }      
  }       
 return instance; 

   }
}
原文地址:https://www.cnblogs.com/lizeyang/p/5535370.html