核心:
构造函数私有化
实现方式
1.饿汉式单例
public class Hungry{
private static final Hungry hungry=new Hungry();
private hungry(){};
public Hungry getHungry(){
return hungry;
}
}
测试:
Hungry hungry=Hungry.getHungry();
Hungry hungry1=Hungry.getHungry();
System.out.println(hungry==hungry1);
结果:
2.懒汉式单例
主要是为了解决在多线程环境下由于抢占 导致对象不是唯一的单例的情况。
//懒汉式单例,主要是处理多线程环境和指令重排
public class LazyMan {
private String name="LazyMan";
private volatile static LazyMan lazyMan;//volatile禁止指令重排和保证变量的内存可见性(指变量修改后会通知各线程变量最新的值)
@Override
public String toString() {
return "LazyMan{" +
"name='" + name + '\'' +
'}';
}
private LazyMan(){
}
public static LazyMan getInstance(){
if(lazyMan==null){//第一次判空,是判断是否已经有lazyMan对象
synchronized (LazyMan.class){//这是一个锁池
//synchronized锁Class对象时,同时只能有一个该类的实例的线程访问到代码块,锁实例对象时,
// 该实例对象被锁住(同时只能有一个该实例对象的线程访问代码块),其它实例对象的线程可以访问该代码块
if(lazyMan==null){
//第二次判空是因为第一次判空时,进来了许多类的实例的线程竞争这个锁,尽管只有一个线程竞争到锁,
// 但是其它活跃的线程会在锁释放后,竞争该锁,如果不加判空条件,竞争到该锁的线程又会创造新的实例,会导致锁池有多少个类的实例线程,就会有多少个该实例。
lazyMan=new LazyMan();
//此处不要使用return new LazyMan():函数执行到这里会跳出,返回的是一个新的对象,不再是lazyMan对象
}
}
}
return lazyMan;
}
}