单例模式
Posted mr-hanexp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
总之就是构造器私有化,提供一个公共的方法创建实例供外部使用。
饿汉式
//饿汉式单例
public class Hungry {
//可能会造成空间的浪费,因为一开始就将这个对象new出来了
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
懒汉式
//懒汉式
public class Lazy {
private Lazy() {
}
private static Lazy lazy;
public static Lazy getInstance() {
if (lazy == null) {
lazy = new Lazy();
}
return lazy;
}
问题
:多线程下会出问题
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(() -> {
Lazy.getInstance();
}
).start();
}
}
/**
多线程下执行创建了多个实例
-----------------------
Thread-0 Ok
Thread-1 Ok
-----------------------
*/
DCL懒汉式
//DCL双重检测锁
public class DCL {
private DCL(){
}
/*加上volatile禁止指令重排,因为下面dcl = new DCL()这个动作不是原子性的,
分为三步:1.分配内存空间。2.执行构造方法初始化对象。3.将这个对象指向这个内存空间。
2和3的执行顺序可能被交换,多线程就有可能造成空指针的异常。
*
*/
private volatile static DCL dcl;
public static DCL getInstance(){
//通过双重检测
if(dcl== null){
//需要锁这个类
synchronized (DCL.class){
if (dcl == null){
dcl = new DCL();
}
}
}
return dcl;
}
多线程下安全,但是能被反射破坏。
静态内部类单例
//静态内部类内部类单例
public class Inner {
private Inner(){}
public static Inner getInstance(){
return InnerClass.INNER;
}
public static class InnerClass{
private final static Inner INNER = new Inner();
}
}
以上方式创建的单例都能够被反射破坏
枚举单例
//枚举单例
public enum ESingle{
INSTANCE;
public ESingle getInstance(){
return INSTANCE;
}
}
安全
因为不能通过反射来进行实例化。
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章