单例
单例模式,是一种设计模式,属于创建型设计模式,还有一种创建型设计模式,工厂模式。
设计模式总共有23种,三大类,六项原则。
三大类分别是:创建型,结构型,行为型。
今天说的就是:初中级工程师面试问的最多的,单例模式。
面试问题
什么是单例模式?
答:保证JVM只能有一个实例。
单例的两种实现方式
懒汉
饿汉
区别
懒汉式--- 线程不安全,需要时才创建。
饿汉式--- 线程天生安全,jvm class加载的时候就初始化。
举例
懒汉式例子
/**
* 单例的含义:保证在jvm中只能有一个实例
*/
class Singleton{
private static Singleton singleton;
/**懒汉式
*
* 私有化构造方法 不能直接new
*/
private Singleton(){
}
/**
* 提供方法,保证返回一个实例
* 2.方法加上synchronized 只能允许一个线程访问getSingleton方法,保证了线程安全问题。(效率低)
* 3.换成双重检验锁
* @return
*/
public static Singleton getSingleton(){
//第一层锁
if(null == singleton){
synchronized (Singleton.class){
//第二层锁 双重检验锁 部分线程不走同步方法,提高效率。
if(null == singleton){
singleton = new Singleton();
}
}
}
return singleton;
}
}
上面代码解释一下,最开始的版本是如下的:
public static synchronized Singleton getSingleton() {
if (null == singleton) {
singleton = new Singleton();
}
return singleton;
}
为了保证不出现线程安全问题,也就是多个线程同时执行该方法时,多次创建,产生多个实例。方法上加上了synchronized 关键字。
但是如此操作,效率会很低。
我们如下思考:
1.只有singleton ==null 的 情况下,才会去创建对象实例,而并非所有线程进入该方法,singleton都等于null。
2.因此方法上加上 synchronized ,等于该方法都是一次只能有一个线程执行,效率降低。
3.解决方法就是第一种,双重检验锁。部分singleton 已经不等于null的线程,直接返回即可,无需等待同步锁释放,效率提高。
饿汉式例子
class Singleton{
/**
* 饿汉式 当class文件被加载的时候 就初始化对象
*/
private static Singleton singleton = new Singleton();
/**
* 私有化构造方法 不能直接new
*/
private Singleton(){
}
public static Singleton getSingleton2(){
return singleton;
}