单例模式——《设计模式》

橙三吉。 提交于 2020-01-25 04:01:31

概念

什么是单例模式?

首先,单例模式,属于创建型设计模式。
许多时候系统只需要拥有一个全局类,这样为了协调系统整体的行为。也就是说单例对象的类只能允许一个实例存在。

单例模式的优缺点

优点

  1. 在内存中只有一个对象,节省内存空间;
  2. 避免频繁的创建销毁对象,可以提高性能;
  3. 避免对共享资源的多重占用,简化访问;
  4. 为整个系统提供一个全局访问点。

缺点

  1. 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
  2. 如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;

单例模式的实现

这里主要介绍两种:饿汉式单例、懒汉式单例

一、饿汉式单例

//饿汉式单例类.在类初始化时,已经自行实例化 
public class Singleton1 {
    private Singleton1() {}
    private static final Singleton1 single = new Singleton1();
    //静态工厂方法 
    public static Singleton1 getInstance() {
        return single;
    }
}

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

二、懒汉式单例

//懒汉式单例类.在第一次调用的时候实例化自己 
public class Singleton {
    private Singleton() {}
    private static Singleton single=null;
    //静态工厂方法 
    public static Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
    }
}

上面懒汉式单例的实现没有考虑线程安全问题,它是线程不安全。并发环境下很可能出现多个Singleton实例,要实现线程安全。

优化
1、在getInstance方法上加同步

public static synchronized Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
}

2、双重检查锁定

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

3、静态内部类

public class Singleton {  
    private static class LazyHolder {  
       private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
       return LazyHolder.INSTANCE;  
    }  
}

这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

饿汉式和懒汉式区别

懒汉就是只有调用getInstance的时候,才回去初始化这个单例。

饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,

线程安全

饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面这几种实现,他们在资源加载和性能方面有些区别。

什么是线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。反之就不是线程安全。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!