单例模式定义:
单例模式(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; } }