在讲解多线程的单例时,先说一下单例

    饿汉单例

    饿汉单例相对比较好理解,就是在单例类加载的时候就初始化需要单例的对象

  

public class Singleton{
    private static Stu stuObj = new Stu();

    public static Log getInstance(){
        return stuObj;
    }
}

 

   懒汉单例

   懒汉模式,就是当你用到才初始化

   

public class Singleton{
    private static Stu stuObj = null;

    public static Log getInstance(){
        if(stuObj == null){
            stuObj = new Stu();
        }
        return stuObj;
    }
}

 

1.方法中声明synchronized关键字

      出现非线程安全问题,是由于多个线程可以同时进入getInstance()方法,那么只需要对该方法进行synchronized的锁同步即可:

package org.mlinge.s03;  
  
public class MySingleton {  
      
    private static MySingleton instance = null;  
      
    private MySingleton(){}  
      
    public synchronized static MySingleton getInstance() {  
        try {   
            if(instance != null){//懒汉式   
                  
            }else{  
                //创建实例之前可能会有一些准备性的耗时工作   
                Thread.sleep(300);  
                instance = new MySingleton();  
            }  
        } catch (InterruptedException e) {   
            e.printStackTrace();  
        }  
        return instance;  
    }  
}  

 

 2.同步代码块实现

     

package org.mlinge.s03;  
  
public class MySingleton {  
      
    private static MySingleton instance = null;  
      
    private MySingleton(){}  
      
    //public synchronized static MySingleton getInstance() {  
    public static MySingleton getInstance() {  
        try {   
            synchronized (MySingleton.class) {  
                if(instance != null){//懒汉式   
                      
                }else{  
                    //创建实例之前可能会有一些准备性的耗时工作   
                    Thread.sleep(300);  
                    instance = new MySingleton();  
                }  
            }  
        } catch (InterruptedException e) {   
            e.printStackTrace();  
        }  
        return instance;  
    }  
}  

这里的实现能够保证多线程并发下的线程安全性,但是这样的实现将全部的代码都被锁上了,同样的效率很低下。

4. Double Check Locking 双检查锁机制(推荐)

   为了达到线程安全,又能提高代码执行效率,我们这里可以采用DCL的双检查锁机制来完成,代码实现如下:

  

package org.mlinge.s05;  
  
public class MySingleton {  
      
    //使用volatile关键字保其可见性  
    volatile private static MySingleton instance = null;  
      
    private MySingleton(){}  
       
    public static MySingleton getInstance() {  
        try {    
            if(instance != null){//懒汉式   
                  
            }else{  
                //创建实例之前可能会有一些准备性的耗时工作   
                Thread.sleep(300);  
                synchronized (MySingleton.class) {  
                    if(instance == null){//二次检查  
                        instance = new MySingleton();  
                    }  
                }  
            }   
        } catch (InterruptedException e) {   
            e.printStackTrace();  
        }  
        return instance;  
    }  
}  

这里在声明变量时使用了volatile关键字来保证其线程间的可见性;在同步代码块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。

posted on 2018-03-06 09:07  高尚的动物世界  阅读(207)  评论(0编辑  收藏  举报