设计模式—单例模式

定义:确保某一个类只有一个实例, 而且自行实例化并向整个系统提供这个实例(Ensure a class has only one instance, and provide a global point of access to it.)。

实现方式:饿汉模式、懒汉模式、枚举模式、类加载方式、双重检查加锁

1.饿汉模式

public class Singleton
{
    private static final Singleton singleton = new Singleton();
    //通过定义一个私有访问权限的构造函数, 避免被其他类new出来一个对象,限制产生多个对象
    private Singleton(){}
    //通过该方法获得实例对象
    public static Singleton getSingleton(){
            return singleton;
    }
    //类中其他方法,尽量是static
    public static void doSomething(){}
}

饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变
即立即创建,线程安全

2.懒汉模式

public class Singleton {  
     private static Singleton singleton;  
     //限制产生多个对象
     private Singleton (){}
     //通过该方法获得实例对象,通过加锁来控制线程安全
     public static synchronized Singleton getSingleton() {  
     if (singleton == null) {  
          singleton = new Singleton();  
        }  
        return singleton;  
     }  
      //类中其他方法,尽量是static
    public static void doSomething(){}

 }  

懒汉式优点是延时加载、 是在需要的时候才创建对象,通过加锁的方式来控制线程安全,否则会出现线程不安全的情况,但同步情况下效率低。例如A,B两个线程同时请求资源,如果A的请求还没有完成B的请求就来了,就会出现很多种情况,线程是不安全的。
即延迟加载,线程安全

3.双重检查加锁

       public class Singleton {  
          private static volatile Singleton singleton; 
          //限制产生多个对象
          private Singleton (){}   

          public static Singleton getSingleton() { 
           //先检查对象实例是否存在 
              if (singleton == null) {  
                 //同步块,线程安全的创建实例
                      synchronized (Singleton.class) {  
                   //再次检查实例是否存在,如果不存在才真正的创建实例
                 if (singleton == null) {  
                     singleton = new Singleton();  
                 }  
              }  
          }  
         return singleton;  
         }  
          //类中其他方法,尽量是static
          public static void doSomething(){}

     }  

延迟加载:在需要的时候才创建对象
线程安全
同步情况下效率高:先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的 情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

volatile类型变量可以保证写入对于读取的可见性,保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。同时禁止进行指令重排序,JVM不会将volatile变量上的操作与其他内存操作一起重新排序,volatile变量不会被缓存在寄存器,因此保证了检测instance状态时总是检测到instance的最新状态。

4.静态内部类加载方式

 public class Singleton implements java.io.Serializable ,Cloneable {  
          //静态内部类
          private static class SingletonHolder {  
               private static final Singleton INSTANCE = new Singleton();  
          } 
           //限制产生多个对象
          private Singleton (){}
          //公开的唯一访问点
          public static final Singleton getInstance() { 
              return SingletonHolder.INSTANCE;  
          }  
          //自定义反序列化返回的对象
          private Object readResolve() throws ObjectStreamException{
                return getInstance();
          }
          private Object clone() throws CloneNotSupportedException{
                return getInstance();
         }
  }  

延迟加载
同步情况下效率高
实现麻烦
自由序列化:实现java.io.Serializable ,Cloneable接口后防止反序列化
线程安全:由于内部类不会在类的外部被使用,所以只有在调用getInstance()方法时才会被加载。同时依赖JVM的ClassLoader类加载机制保证了不会出现同步问题。

5.枚举模式

   public enum Singleton {  
         INSTANCE;  
       public void doSomething() {
          System.out.println("Something");
        }  

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

立即加载
实现简单
自由序列化:因为每一个枚举类型和枚举变量在JVM中都是唯一的,即Java在序列化和反序列化枚举时做了特殊的规定,不存在实现序列化接口后调用readObject会破坏单例的问题。
线程安全:由于枚举类的会在编译期编译为继承自java.lang.Enum的类,其构造函数为私有,不能再创建枚举对象,枚举对象的声明和初始化都是在static块中,保证了线程的安全性。但是不能实现延迟加载,保证单例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值