zoukankan      html  css  js  c++  java
  • 单例模式-解决线程冲突

    单例模式的使用


    单例创建用户服务对象没必要给每个用户都创建一个
    单例 :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

  • 相关阅读:
    ye间模式
    Xutilt网络获取数据
    JUnit
    IntelliJ IDEA快捷键
    Map存放不同数据或对象
    SQL改
    外键约束
    Hibernate之SQL语言查询
    Hibernate之Criteria语言查询
    Hibernate之HQL语言查询
  • 原文地址:https://www.cnblogs.com/yzuzhang/p/5594519.html
Copyright © 2011-2022 走看看