饿汉式:线程安全的

  • 静态常量写法

    Class Bank{
      //私有化类的构造器,类的外部无法通过构造器new对象
      private Bank(){
      }
    
      //内部创建类的对象,此对象也是静态的,因为静态方法只能调静态对象
      private static Bank instance = new Bank();
    
      //提供公共的静态方法,返回类的对象。这样就可以巧妙的避开在类的外部new对象
      public static Bank getInstance(){
          return instance;
      }
    }
    psvm{
      Bank b1 = Bank.getInstance();
      Bank b2 = Bank.getInstance();
         sout(b1 == b2);//true,都是类中new的对象
    }

    优点:类装载时就完成了实例化,避免了线程同步的问题
    缺点:类装载时就完成实例化,如果从始至终没有用过这个实例,造成内存的浪费

  • 静态代码块写法

    Class Bank{
      //私有化类的构造器,类的外部无法通过构造器new对象
      private Bank(){
      }
    
      //内部创建类的对象,此对象也是静态的,因为静态方法只能调静态对象
      private static Bank instance;
    
          static{
              instance = new Bank();
              }
    
      //提供公共的静态方法,返回类的对象。这样就可以巧妙的避开在类的外部new对象
      public static Bank getInstance(){
          return instance;
      }
    }
    psvm{
      Bank b1 = Bank.getInstance();
      Bank b2 = Bank.getInstance();
         sout(b1 == b2);//true,都是类中new的对象
    }

    优缺点同上

    懒汉式

  • 线程不安全写法

    Class Bank{
           private static Bank instance;
       private Bank(){}
       public static Bank getInstance(){
           if(instance== null){
           instance = new Bank();
           }return instance;
       }
    }

    优点:起到了用的时候才创建的效果,
    缺点:但只在单线程下是线程安全的。多线程下可能产生多个实例

  • 线程安全写法

    Class Bank{
           private static Bank instance;
       private Bank(){}
    //加入同步处理代码,解决多线程不安全的问题
       public static synchronized Bank getInstance(){
           if(instance == null){
           instance= new Bank();
           }return instance;
       }
    }

    优点:解决类线程安全的问题
    缺点:效率变低,每次都需要去进行同步检测

  • 双重检查方式

    Class Bank{
           private static volatile Bank instance;
       private Bank(){}
    //加入同步处理代码,解决多线程不安全的问题
       public static synchronized Bank getInstance(){
                   Synchronized(Bank.class){
           if(instance == null){
               nstance= new Bank();
           }return instance;
       }
    }
  • 静态内部类写法,推荐

    Class Bank{
           private static volatile Bank instance;
       private Bank(){}
    //静态内部类
           private static class SingletonInstance(){
               private static final Bank INSTANCE = new Bank();             
    }
       public static synchronized Bank getInstance(){
                   return SingletonInstance.INSTANCE;
       }
    }

    优点:

    • 类装载机制保证初始化实例时只有一个线程
    • SingletonInstance被装载时不会立即实例化,,而是在需要时调用,才会装载
    • 静态内部类只会在第一次加载类时初始化,JVM保证了线程的安全,在类的初始化时,别的线程无法进入
    • 避免了线程不安全,同时也延迟加载,效率高