GOF23之单例模式(手撕代码)
1、单例模式
饿汉式
package com.itheima.kiki.single;
/**
* 饿汉式单例
* 构造器私有,一旦私有构造器,别人就无法new对象了,保证内存中只有一个对象
*
*/
public class HungaryDemo {
//构造器私有
private HungaryDemo(){
}
//创建对象
private final static HungaryDemo HUNGARY_DEMO = new HungaryDemo();
//返回对象实例
public static HungaryDemo getInstance(){
return HUNGARY_DEMO;
}
}
懒汉式
package com.itheima.kiki.single;
/**
* 懒汉式单例
*/
public class LazyDemo {
private LazyDemo(){
System.out.println(Thread.currentThread().getName()+ "ok");
}
private volatile static LazyDemo lazyDemo;
public static LazyDemo getInstance(){
//双重检测锁模式的懒汉式单例(DCL懒汉式)
if(lazyDemo == null){
synchronized (LazyDemo.class){
if (lazyDemo == null){
lazyDemo = new LazyDemo();//不是原子性操作
/**
* 1、分配内存空间
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
* 123
* 132 A线程
* B线程 此时lazyDemo还没有完成构造
*
*/
}
}
}
return lazyDemo;
}
//多线程并发
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
new Thread(()->{
lazyDemo.getInstance();
}).start();
}
}
}
破坏单例
package com.itheima.kiki.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* 懒汉式单例
*/
public class LazyDemo2 {
private static boolean kiki = false;
private LazyDemo2(){
synchronized (LazyDemo2.class){
if (kiki==false){
kiki=true;
}else {
throw new RuntimeException("不要试图使用反射破坏异常");
}
}
System.out.println(Thread.currentThread().getName()+ "ok");
}
private volatile static LazyDemo2 lazyDemo;
public static LazyDemo2 getInstance(){
//双重检测锁模式的懒汉式单例(DCL懒汉式)
if(lazyDemo == null){
synchronized (LazyDemo2.class){
if (lazyDemo == null){
lazyDemo = new LazyDemo2();//不是原子性操作
}
}
}
return lazyDemo;
}
//反射
public static void main(String[] args) throws Exception{
//LazyDemo2 instance = LazyDemo2.getInstance();
Field kiki = LazyDemo2.class.getDeclaredField("kiki");
kiki.setAccessible(true);
Constructor<LazyDemo2> declaredConstructor = LazyDemo2.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);//设置无视私有构造器
LazyDemo2 instance = declaredConstructor.newInstance();
kiki.set(instance,false);
LazyDemo2 instance2 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance2);
}
}