创建型模式-单例模式

  1. 定义

无论在什么情况下,定义为单例的类只有一个实例。

  1. 实现思想
    单例模式的实现思想是,通过把构造器私有化,提供一个唯一的访问点返回该类的对象,达到不重复构造该类的目的。
  2. 应用场景
    配置文件的加载,使用线程池获取一个线程等。
  3. 几种实现方式
    懒汉式实现
    第一种
/**
 * 不使用synchronized关键字,存在线程安全问题
 * 使用之后,性能低
 */
public class LazySimpleSingletion {
    private static LazySimpleSingletion instance;
    private LazySimpleSingletion(){}

    public synchronized static LazySimpleSingletion getInstance(){
        if(instance == null){
            instance = new LazySimpleSingletion();
        }
        return instance;
    }
}

第二种

/**
 * 把synchronized放到方法内部,必须使用双重检,如果内部不检查,会创 
 *   建多个实例
 * 如果不使用volatile关键字,存在指令重排序的问题
 */
public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton instance;
    private LazyDoubleCheckSingleton(){}

    public static LazyDoubleCheckSingleton getInstance(){
        //检查是否要阻塞
        if (instance == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                //检查是否要重新创建实例
                if (instance == null) {
                    instance = new LazyDoubleCheckSingleton();
                    //指令重排序的问题
                }
            }
        }
        return instance;
    }
}

第三种

/**
 * 使用内部类的方式实现,写法优雅,但是会被反射破坏
 * 如果不想被反射破坏,需要在构造器中做判断,这样使代码可读性变差
 */
public class LazyStaticInnerClassSingleton {

    private LazyStaticInnerClassSingleton(){
//        if(LazyHolder.INSTANCE != null){
//            throw new RuntimeException("不允许非法访问");
//        }
    }

    static LazyStaticInnerClassSingleton getInstance(){
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder{
        private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
    }

}

饿汉式实现

/**
* 优点:执行效率高,性能高,没有任何的锁
* 缺点:某些情况下,可能会造成内存浪费
*/
public class HungrySingleton {

  private static final HungrySingleton hungrySingleton = new HungrySingleton();

  private HungrySingleton(){}

  public static HungrySingleton getInstance(){
      return  hungrySingleton;
  }
}
public class HungryStaticSingleton {
    //先静态后动态
    //先上,后下
    //先属性后方法
    private static final HungryStaticSingleton hungrySingleton;

    //装B 写法,和上面的实现方式没有区别
    static {
        hungrySingleton = new HungryStaticSingleton();
    }

    private HungryStaticSingleton(){}

    public static HungryStaticSingleton getInstance(){
        return  hungrySingleton;
    }
}

注册式
使用容器的思想,初次实例化把实例对象放到容器中,以后再取从容器中获取。

public class ContainerSingleton {

    private ContainerSingleton(){}

    private static Map<String,Object> ioc = new ConcurrentHashMap<String, Object>();

    public static Object getInstance(String className){
        Object instance = null;
        if(!ioc.containsKey(className)){
            try {
                instance = Class.forName(className).newInstance();
                ioc.put(className, instance);
            }catch (Exception e){
                e.printStackTrace();
            }
            return instance;
        }else{
            return ioc.get(className);
        }
    }
}

ThreadLocal
使用这种方式保证单线程中是单例的,不同线程之间是多例的。

public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocaLInstance =
            new ThreadLocal<ThreadLocalSingleton>(){
                @Override
                protected ThreadLocalSingleton initialValue() {
                    return new ThreadLocalSingleton();
                }
            };
    
    private ThreadLocalSingleton(){}

    public static ThreadLocalSingleton getInstance(){
        return threadLocaLInstance.get();
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容