单例模式
1.饿汉式单例模式
/**
* 饿汉式单例模式,一加载就创建单例对象
*/
public class Hungry {
private Hungry(){
}
private static final Hungry hungry = new Hungry();
public static Hungry getInstance(){
return hungry;
}
}
2.懒汉式单例模式
/**
* 懒汉式单例模式
*/
public class LazyMan {
private LazyMan() {
System.out.println(Thread.currentThread().getName());
}
private static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan==null){
lazyMan = new LazyMan();
}
return lazyMan;
}
// 多线程并发创建对象存在问题。
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
3.双重检测锁单例模式DCL
相对比较安全创建单例的模式,但是反射可以破坏
/**
* 懒汉式单例模式
*/
public class LazyMan01 {
private LazyMan01(){
System.out.println(Thread.currentThread().getName());
}
// 加上volatile关键字禁止指令重排
private volatile static LazyMan01 lazyMan01;
/**
* 双重检测锁模式,DCL懒汉式
* @return
*/
public static LazyMan01 getInstance(){
if (lazyMan01==null){
synchronized(LazyMan01.class){
if (lazyMan01==null){
lazyMan01 = new LazyMan01();// 不是原子性操作,可能会有指令重排
/*
* 1.分配内存空间
* 2.执行构造器,初始化对象
* 3.把对象指向内存空间
* 正常情况下:按照123执行;发生指令重排,可能会先执行132
* 多线程情况下:如果第一个线程执行了13,此时第二个线程过来可能就会判断lazyMan01不为空,直接就返回了lazyMan01
* 此时,lazyMan01对象内存空是空的。
* */
}
}
}
return lazyMan01;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan01.getInstance();
}).start();
}
}
}
4.静态内部类创建单例模式
/**
* 静态内部类创建单例模式
*/
public class LazyMan02 {
private LazyMan02(){
}
public static LazyMan02 getInstance(){
return InnerClass.lazyMan02;
}
static class InnerClass{
private static final LazyMan02 lazyMan02 = new LazyMan02();
}
}
5.枚举创建单例
public enum EnumSingle {
INSTANCE;
public static EnumSingle getInstance(){
return INSTANCE;
}
}