概述:单例模式就是保证在内存中只存在一个实例。像Mgr,Factory这种就只需要一个实例。单例的核心在于私有化构造方法。
饿汉式:简单,推荐使用!
public class Hungry {
private static final Hungry INSTANCE = new Hungry();
// 构造方法私有化
private Hungry(){
}
private static Hungry getInstance(){
return INSTANCE;
}
}
懒汉式
为了解决饿汉式的问题,懒汉式的缺点式按需加载。有两种实现方法,一种式同步方法一种是同步代码块。
同步方法:
public class Lazy2 {
private static Lazy2 INSTANCE;
private Lazy2(){
}
public synchronized static Lazy2 getInstance() throws InterruptedException {
if (INSTANCE==null){
INSTANCE = new Lazy2();
}
return INSTANCE;
}
}
同步代码块:双重检查
public class Lazy3 {
private static volatile Lazy3 INSTANCE;
//volatile关键字可以保证多线程模式下内存的可见性和禁止指令重排
private Lazy3(){
}
public static Lazy3 getInstance() throws InterruptedException {
if (INSTANCE==null){
//这里可能被线程打断 已经完成判断之后被打断 打断的线程完成实例的创建 打断回来之后此线程会再一次创建实例
synchronized (Lazy3.class) {
//所以进入同步代码块还需要再判断一次
if (INSTANCE == null)
INSTANCE = new Lazy3();
}
}
return INSTANCE;
}
}
静态内部类方法
在外部类加载时不会被加载,此时解决了懒加载的问题,又由JVM保证线程安全,因为在JVM中一个类只能被加载一次。
public class StaticInnerClassMethod {
private StaticInnerClassMethod(){
}
//定义一个内部类 内部类中有一个外部类的变量 需要时加载内部类的变量
private static class StaHolder{
private final static StaticInnerClassMethod INSTANCE =
new StaticInnerClassMethod();
}
public static StaticInnerClassMethod getInstance(){
return StaHolder.INSTANCE;
}
}
枚举
这是目前实现单例模式是目前最完美的一种实现方式,使用枚举类型的特性(枚举类型无法被反编译)完成了单例模式,有效防止反序列化。
public enum PerfectMethods {
INSTANCE;
//测试
public static void main(String[] args) {
for (int i = 0; i < 100 ; i++) {
new Thread(()->{
System.out.println(PerfectMethods.INSTANCE.hashCode());
}).start();
}
}
}



