zoukankan      html  css  js  c++  java
  • Java单例模式

    什么是单例模式

      单例模式是在程序中,一个类保证只有一个实例,并提供统一的访问入口。

    为什么要用单例模式

    • 节省内存 节省计算
      • 如对象实例中的一样的,那就不用每次都创建一个对象
    • 方便管理
      • 因为单例提供一个统一的访问入口,不需要创建N多个对象,很多工具类都用了单例实现,如日志、字符串工具类
    • 保证结果正确
      • 比如统计网站的访问次数等等

    单例的实现方式

    • 饿汉式
      • 程序启动的时候就会实例化
     1 public class Singleton {
     2     
     3     private static Singleton singleton = new Singleton();
     4     
     5     private Singleton(){}
     6     
     7     public static Singleton getInstance(){
     8         return singleton;
     9     }
    10 }

      饿汉静态代码块形势

     1 public class Singleton {
     2 
     3     private static Singleton singleton;
     4     static {
     5         singleton = new Singleton();
     6     }
     7     private Singleton(){}
     8 
     9     public static Singleton getInstance(){
    10         return singleton;
    11     }
    12 }
    • 懒汉式
      • 非线程安全的实现
     1 public class Singleton {
     2 
     3     private static Singleton singleton;
     4     private Singleton(){}
     5 
     6     public static Singleton getInstance(){
     7         if (singleton == null){
     8             return singleton = new Singleton();
     9         }
    10         return singleton;
    11     }
    12 }
      • 线程安全的实现,单性能低
     1 public class Singleton {
     2 
     3     private static Singleton singleton;
     4     private Singleton(){}
     5 
     6     public static synchronized Singleton getInstance(){
     7         if (singleton == null){
     8             return singleton = new Singleton();
     9         }
    10         return singleton;
    11     }
    12 }
      • 线程安全的实现,双重校验
        • 注意:两个校验都必须加,如果第二个没有加校验,当两个线程都通过了第一个if校验,此时会有一个线程进入同步代码块,创建singleton实例,接着第二个线程也会进入同步代码块,并会在创建一个singleton。那么这样就破坏了单例。如果不加第一个if校验,那么所有的程序就会串行执行,影响执行效率。所以两个校验都必须存在
     1 public class Singleton {
     2     /**由于 return singleton = new Singleton(); 这行代码在JVM中会分为三步处理
     3      * 1.给singleton分配内存空间
     4      * 2.调用singleton的构造函数开初始化
     5      * 3.将singleton对象指向分配的内存空间(这步执行了就singleton就不是null了)
     6      * 
     7      * 由于CPU会对这三个步骤重排序,如果顺序是1 3 2,那么就可能出现singleton就不是空的,但并没有初始化singleton
     8      * 这样第二个线程可能拿到的就是为初始化的singleton,所以使用volatile来修饰singleton,防止重排序的问题
     9      */
    10     private static volatile Singleton singleton;
    11     private Singleton(){}
    12 
    13     public static Singleton getInstance(){
    14         if (singleton == null){
    15             synchronized (Singleton.class) {
    16                 if (singleton == null) {
    17                     return singleton = new Singleton();
    18                 }
    19             }
    20         }
    21         return singleton;
    22     }
    23 }
      • 懒汉之静态内部类的方式
        • 这种方式能保证线程的安全线性,当Singleton被装载时,并不会立刻实例化静态内部类SingletonInstance,而是在需要时才会实例化
     1 public class Singleton {
     2     
     3     private static class SingletonInstance{
     4         private static final Singleton singleton = new Singleton();
     5     }
     6     private Singleton(){}
     7 
     8     public static Singleton getInstance(){
     9         return SingletonInstance.singleton;
    10     }
    11 }
    • 枚举实现单例
      • 实现简单、线程安全、可以防止反序列化、反射的方式破坏单例模式,如果通过反序列化或反射的方式创建实例,会抛出异常。这种方式是最好的实现的方式
    1 public enum Singleton{
    2   INSTANCE;
    3   public void whateverMethod(){
    4   }    
    5 }

      

  • 相关阅读:
    php魔术常量,_CLASS_,_METHOD_,_FUNCTION_
    php里parent,::和self的分别
    rewrite例子集合
    PHP中::、->;、self、$this操作符的区别
    php中const和define的区别
    aliyun二级域名绑定
    数组操作函数8
    http 301 和 302的区别
    lnmp引发的fpm502错误!
    关于php下开发的跨域问题总结(全)
  • 原文地址:https://www.cnblogs.com/aaronzheng/p/12111931.html
Copyright © 2011-2022 走看看