设计模式之单例模式

单例模式的作用是保证整个程序在一次运行的中,这个类的对象有且只有一个,在struts1中的action就是单例模式,但到了struts2就变成了,action对象为每个请求产生一个实例。本文将描述几种单例模式实现的方案

从分类上来讲,可以分为饿汉式单例模式和懒汉式单例模式

  懒汉式单例模式:在类加载时不初始化

  饿汉式单例模式:在类加载时就完成初始化,因此类加载的速度会比较慢,但获取对象快

基本实现思路

  1、构造方法私有,没法从外部直接new对象

  2、对外部提供获取该类的实例的静态方法

  3、在类的内部创建对象,通过2的方法返回

1、饿汉式(没有实现延迟加载)

 1 public class SimpleSingleton {
 2   //唯一实例
 3   private static SimpleSingleton  instance = new SimpleSingleton ();
 4   // 返回唯一实例
 5   public static SimpleSingleton getInstance(){
 6     return instance;
 7   }
 8   //构造方法私有
 9   private SimpleSingleton (){}
10 }

这种方法有一个缺点,在虚拟机加载类的时候,会在初始化阶段就为静态变量赋值,没有实现延迟加载(尽可能晚的实例化对象,避免在类加载的过程中让虚拟机去创建这个对象)

2、饿汉式

public class SimpleSingleton {
   //唯一实例
   private static SimpleSingleton  instance = null;
   static{
    instance = new SimpleSingleton();
  }
  private static SimpleSingleton getInstance(){
    return instance;
  }
  //构造方法私有
  private SimpleSingleton (){}
}

看起来差别挺大的,但是和1差不多,都是在类初始化的时候实例化instance

3、静态内部类(推荐)

public class Singleton {
    private static class SingletonHolder{
        private static final Singleton instance = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInsatance(){
        return SingletonHolder.instance;
    }
}

这一种方式,比1、2更加合理,使用了静态内部类,在外部类被加载的时候,instance不一定会被初始化,因为内部类没有被主动的使用,

4、懒汉式(线程不安全)

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

延迟加载,并且多线程出问题

5、懒汉式(线程安全)

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

对方法加了锁,多线程能很好工作,也实现了延迟加载,但是效率很低,很多情况下也不需要同步

6、懒汉式(同步代码块)

public class Singleton {

    private static Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

因为5的效率太低了,所以使用同步代码块的方法,但是这样真的起作用了吗?线程1通过If判断,此时线程2也通过if判断,还是会产生多个实例

7、双重检验锁(推荐)

public class Singleton {

    private static volatile Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

为了防止6的问题,那么判断2次就好了,实例化代码只执行一次

8、枚举(推荐)

public enum Singleton {
    INSTANCE;
    public void whateverMethod() {}
}

JDK1.5之后添加的,能避免多线程的同步问题,还能防止反序列化重新创建新的对象

原文地址:https://www.cnblogs.com/ccxka/p/9596830.html