核心:

       构造函数私有化

实现方式

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;
}
}