单例模式的应用(1)

单例模式定义:


单例模式(Singlleton Pattern) 是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。单例模式在现实生活中应用也非常广泛,例如公司CEO,部门经理等。J2EE标准中的ServletContext、ServletContextConfig等,Spring框架应用中ApplicationContext、数据库的连接池等也都是单例形式。


一、饿汉式单例

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


优点:保证线程绝对安全,执行效率高,没有任何的锁


缺点:所有对象类加载的时候就实例化,系统初始化就会导致大量的内存浪费


//饿汉式单例类.在类初始化时,已经自行实例化 
public class Singleton {
    private Singleton() {}
    private static final Singleton single = new Singleton();
    //静态工厂方法 
    public static Singleton 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;
    }
}


针对上述懒汉式单例存在线程安全,在多线程情况下,会生成多个实例,不满足单例模式;所以提出如下饿汉式线程安全单例模式

饿汉式线程安全


public class Singleton {
    private Singleton() {}
    private static Singleton single=null;
    //静态工厂方法 
    public static synchronized Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
 }
}


  • 通过使用synchronized加锁时,在线程比较多的情况下,如果CUP分配压力上升,则会导致大批线程阻塞,从而导致程序性能下降。那么就引出了下边的双重检查锁的单例模式,(备注:synchronized是互斥锁,同一时刻只有一个线程能够访问方法)

双重检查锁


public class Singleton {
    private Singleton() {}
    private static volatile Singleton single=null;
    public static Singleton getInstance() {
         //第一层:双重检查锁的作用  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
            //第二层:是为了减少线程对同步锁的竞争
               if (singleton == null) {  
                  singleton = new Singleton(); 
               }  
            }  
        }  
        return singleton; 
    }


单例模式-双重检查加锁为什么需要加上volatile关键字?

双重检查锁单例模式为什么要用volatile关键字?


上述的双重检查锁虽然做了优化,但是仍然要使用synchronized关键字,对程序性能还是存在一定影响的。于是我们引入了如下的静态内部类形式的单例,从类初始化的角度来考虑,看如下代码采用了静态内部类的方式。


静态内部类

优点:写法优雅,利用了Java本身语法特点,性能奥,避免了内存浪费

缺点:能够被反射破坏


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



上一篇:Docker——项目实战(六)(4)


下一篇:Docker——项目实战(六)(2)