美文网首页
设计模式(单例模式)

设计模式(单例模式)

作者: Chenyangqi | 来源:发表于2020-11-06 11:06 被阅读0次

    1、饿汉式

    • 优点:类加载的时候完成实例化,避免了线程同步问题
    • 缺点:在类加载的时候就完成实例化,没有达到Lazy Loading的效果,如果该类未使用则造成了内存浪费

    可以通过静态变量和静态代码块两种方式实现,效果一样

    public class Singleton1 {
       //方式1:通过静态变量方式创建
       private static final Singleton1 INSTANCE = new Singleton1();
    
       //方式2:通过静态代码块的方式,效果和方法1一样
    //    private static final Singleton1 INSTANCE;
    //
    //    static {
    //        INSTANCE = new Singleton1();
    //    }
    
       /**
        * 私有的构造方法,防止产生多个对象
        */
       private Singleton1() {
       }
    
       /**
        * 通过该方法获得实例
        *
        * @return
        */
       public static Singleton1 getInstance() {
           return INSTANCE;
       }
    
       public void doSomething() {
    
       }
    }
    

    可通过如下方式,在多个线程中创建多个单例对象,查看创建的对象hashCode是否相同判断是否为单例

    Executor executor = Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        //测试饿汉式单例
                        Singleton1 singleton1 = Singleton1.getInstance();
                        Singleton1 singleton2 = Singleton1.getInstance();
                        System.out.println(singleton1.hashCode() + "\t-----\t" + singleton2.hashCode());
                    }
                });
            }
    

    打印结果如下,不同线程下的Singleton1对象都是同一个HashCode,表示是全局单例

    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    2007961061  -----   2007961061
    

    2、懒汉式-线程不安全

    • 优点:做到了懒加载
    • 缺点:多线程使用的时候会产生多个实例,实际开发中不要使用这种方案
    public class SingLeton2 {
       private static SingLeton2 INSTANCE;
    
       private SingLeton2() {
       }
    
       public static SingLeton2 getInstance() {
           if (INSTANCE == null) {
               INSTANCE = new SingLeton2();
           }
           return INSTANCE;
       }
    }
    

    多线程创建此单例hashcode如下,存在hashCode不一致的问题,所有没有做到全局单例

    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1523178316  -----   1523178316
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    1337000531  -----   1337000531
    

    3、懒汉式 线程安全

    • 优点:加了同步,线程安全
    • 缺点:效率太低,开发中不推荐使用这种写法
    public class Singleton3 {
    
       private static Singleton3 INSTANCE;
    
       private Singleton3() {
       }
    
       public static synchronized Singleton3 getINSTANCE() {
           if (INSTANCE == null) {
               INSTANCE = new Singleton3();
           }
           return INSTANCE;
       }
    }
    

    下面这种方式,虽然加锁了但是还是存在线程不安全的问题,同一时刻不同的线程走到if(instance==null)这一步时,还是会创建不同的对象

    //方式二 线程不安全
       static class  Singleton7{
           private static Singleton7 instance;
    
           private Singleton7(){}
    
           public static Singleton7 getInstance() {
               if(instance==null){
                   synchronized (Singleton7.class){
                       instance=new Singleton7();
                   }
               }
               return instance;
           }
       }
    

    4、双重检查

    • 优点:线程安全,延迟加载,效率高
    • 开发中推荐使用这种方案
    public class Singleton4 {
      private static volatile Singleton4 instance;
    
      private Singleton4() {
      }
    
      public static Singleton4 getInstance() {
          if (instance == null) {
              synchronized (Singleton4.class) {
                  if (instance == null) {
                      instance = new Singleton4();
                  }
              }
          }
          return instance;
      }
    }
    

    5、静态内部类

    • 优点:线程安全,也做到了懒加载,开发中推荐使用
    public class Singleton5 {
       private Singleton5() {
       }
    
       private static class Singleton5Instance {
           private static final Singleton5 INSTANCE = new Singleton5();
       }
    
       public static Singleton5 getInstance() {
           return Singleton5Instance.INSTANCE;
       }
    }
    

    6、枚举方式创建单例

    • <<Effective Java>>推荐使用这种方式创建单例,项目中推荐使用
    public enum Singleton6 {
       INSTANCE;
    
       public void doSomething() {
           System.out.println("枚举创建");
       }
    
       private String name;
    
       public String getName() {
           return name;
       }
    
       public void setName(String name) {
           this.name = name;
       }
    }
    

    相关文章

      网友评论

          本文标题:设计模式(单例模式)

          本文链接:https://www.haomeiwen.com/subject/ycqtbktx.html