单例模式-解决线程冲突

单例模式的使用


单例创建用户服务对象没必要给每个用户都创建一个
单例 :1 构造方法私有化 

    2 创建一个私有的静态变量

        3 公共的静态方法 当做入口

第一种单例模式

问题 : 预先加载,没有手动实例化变量的时候 已经实例化了变量

当你要使用对象的时候,只是把这个变量给你,构造方法私有化 外界不能直接访问。

private UserService(){
    //  创建一个私有的静态变量(常量)
    private static final UserService USER_SERVICE = new UserService(); // 3对外提供一个 公共的 静态的 返回该对象实例的一个方法
    public static UserService getInstance(){
        return USER_SERVICE; 
    }
}

 懒汉式

/**
 * 懒汉式 写法1
* 重大缺陷:线程不安全 *
@author Administrator */ public class Singleton {
   //私有化构造函数
private Singleton(){ } private static Singleton singleton=null; //静态工厂方法 public static Singleton getInstance(){ if(singleton==null){ singleton=new Singleton(); } return singleton; } }

饿汉式

/**
 * 饿汉式:类初始化时,实例化。
 * @author Administrator
 * 类初始化时开销大,线程安全
 */
public class Singleton3 {
    private Singleton3(){
        
    }
    private static final Singleton3 singleton=new Singleton3();
    public static Singleton3 getInstance(){
        return singleton;
    }
}

 

第二种同步懒汉式 

问题: 排队严重  严重影响效率

因为每个用户在计算机里面都是一个单独的线程    
当 一个线程 调用UserService 对象以后加了一把锁,别人就访问不了了

/**
 *   单例模式的目标是什么?
 *   是为了让当前类只能产生一个对象    如果 我先后创建了多个还是单例吗?.
 */
private UserService(){
    //构造方法私有化
    private static UserService userService = null;  //先创建一个 静态变量
    public static synchronized UserService getInstance(){  
        if(userService == null){   //如果为空  我返回一个新的  
            userService = new UserService();
        }
    return userService;  //如果不为空 直接返回
}

 

第三种

/**
 * 如果两个线程同时判断了userService是空 进去了 第一个线程创建的疏忽,锁住了,第二个需要瞪大,第一个线程创建完了之后
 * 本来是第二个,我不需要再创建了 ,但是他已经在判断里面了,所以又创建了一个 ,所以说,单例模式没有成功
 * @param user
 */
private UserService(){
    //构造方法私有化
    private static UserService userService = null;
    public static UserService getInstance() {
        if(userService == null){//如果两个或多个线程同时进入这里,判断完成后都为空,那么会创建好多对象吧,单例模式就失效了
        synchronized(UserService.class){//我现在对整个类锁了 
       userService = new
UserService(); } } return userService; }

第四种 双重检测懒汉式

private UserService() {
    // 构造方法私有化
    private static volatile UserService userService = null;// 私有的静态变量

    public static UserService getInstance() {// 获取当前类对象的方法
        if (userService == null) {
          synchronized (UserService.class) {// 现在是对整个类锁住了
            if (userService == null) {// 更上面第三章方法一样,当前就能解决第三种方法的问题(创建了多个对象),因为,就是两个同时进入上面的if判断,到这里,就会判断不通过,就会直接返回一个对象,不会在去创建新的对象
                userService = new UserService();
            }
        }
    }
    return userService;
}

 在双重检测中,使用了 volatile 关键字,能够保证访问到的变量是最后修改的。为什么要加volatile关键字呢?因为在Java中双重

检测很可能导致失败的结果,得到一个存在但未初始化完成的实例。《Java与模式》的总结是:在Java编译器中,Singleton类的初

始化与instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取instance引用,并调用这个对象的方法的

话,可能会发现对象初始化过程尚未完成,从而造成崩溃。

 

第五种 静态内部类

/**
 * 懒汉式:通过静态内部类实现方式,既实现了线程安全,又提高了效率
 * @author Administrator
 *
 */
public class Singleton4 {
    private Singleton4(){
        
    }
    public static Singleton4 getInstance(){
        return Instance.singleton;    //当需要返回实例的时候,初始化创建静态实例对象。
    }
    
    private static class Instance{    
        private static final Singleton4 singleton=new Singleton4();
    }
}

第六种 Enum枚举实现

 

/**
 * 枚举类型实现单例
 * @author Administrator
 *
 */
public class Singleton5 {
    public enum Singleton{
        INSTANCE;
        
        public void method(){
            //任意方法
        }
    }    

    public static void main(String[] args) {
        Singleton.INSTANCE.method();
    }
}

 枚举方法 简洁明了,并提供序列化机制,不会在反序列化实例时创建新实例(在其他单例方法中如果要变成可序列化的,不仅要加

上implements Serializable,还需要提供readResolve方法,参加《effective Java》)。也不会受到反射机制的影响,是实现单例

模式的最佳方法。

 

相关:http://www.cnblogs.com/scecit/p/4853953.html

 

posted @ 2016-06-17 16:53  yzuzhang  阅读(393)  评论(0编辑  收藏  举报