1.单例模式的概念
在程序中只存在一个对象的实例,我们就称这个对象是单例的,这样我们就可以在程序中所有请求都会共享这个对象的属性和方法,单例模式的实现分为两种,一种是饿汉式,一种是懒汉式。
在java中单例模式设计,需要私有化构造方法,对外提供一个获取对象实例的方法。
饿汉式单例模式
饿汉式相对比较简单,而且也不会出现并发问题,顾名思义,就是在程序启动的时候创建对象,下面我们直接看一下饿汉式的代码实现
private static SingleDesign singleDesign = new SingleDesign();
/**
* 私有化构造方法,防止通过调用构造方法创建对象
*/
private SingleDesign(){
}
/**
* 饿汉式单例模式
* @return
*/
public static SingleDesign getInstance(){
return singleDesign;
}
懒汉式单例模式
懒汉式模式就不像饿汉式那样简单了,懒汉式的原则是在第一次需要使用对象实例的时候才去创建对象实例,这个时候会产生并发问题,因为可能会遇到多个线程去请求创建对象,这个时候就产生并发问题了,相信大家这里会想到老生常谈的一个词叫做双重检测单例模式(Double Check Single),对下面我就直接上这段代码,而不是通过错误代码衍生出正确的代码,因为这样有可能会误导读者,让读者对错误的懒汉式代码加深印象,所以我直接上最佳实现的的代码,我会在代码上添加上每一步的注释。
/**
* 对象需要添加volatile关键字
* 防止jvm进行指令重排序,导致singleDesign2对象还没有创建成功,就返回
*/
private volatile static SingleDesign singleDesign2;
private static Object object;
/**
* 私有化构造方法,防止通过调用构造方法创建对象
*/
private SingleDesign(){
}
/**
* 饿汉式单例模式
* @return
*/
public static SingleDesign getInstance2(){
// 优先验证当前对象是否已经被创建,如果已经被创建,则直接返回,否则进入后面流程,这里是为了减少线程竞争同步锁的机会
if(singleDesign2 == null){
// 上同步锁
synchronized (object){
// 二次验证对象是否为空,是为了防止多个线程走到等待锁的时候singleDesign2对象还未null,
// 当获取到锁后,需要验证当前对象是否已经初始化,如果已经初始化则直接返回,要不然这里有可能会多次创建对象,就不是单例的了
if(singleDesign2 == null){
// 创建对象 jvm实际是有三部
// 1.分配内存
// 2.初始化对象
// 3.将内存地址执行对象
singleDesign2 = new SingleDesign();
}
}
}
return singleDesign2;
}