设计模式 之 单例- 2019-10-10 20:40:40- 设计模式: java,编程,设计模式,单例
概念
保证一个类的实例全局只有一个,并提供一个全局访问点。
特性
构造私有化
实现方式 8种
饿汉式
优点:不会产生线程问题,保证唯一单例
缺点;如果不使用时就初始化,会导致无用对象占用系统资源
public class HungrySingleton {
private static final HungrySingleton hungrySingleton = new HungrySingleton();
/**
* 构造私有化
*/
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
}
public class HungrySingletonThread implements Runnable {
@Override
public void run() {
HungrySingleton instance = HungrySingleton.getInstance();
System.out.println(instance);
}
}
懒汉式(线程安全/不安全)
线程不安全
* 优点:节省资源
* 缺点:有线程安全问题
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (null == lazySingleton) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
public class LazySingletonTread implements Runnable {
@Override
public void run() {
LazySingleton laySingleton = LazySingleton.getInstance();
System.out.println(laySingleton);
}
}
线程安全
* 优点:节省内存资源 无线程问题
* 缺点:性能下降 资源占用时间过长 ,会锁住整个类
public class LazySyncSingleton {
private static LazySyncSingleton lazySingleton = null;
private LazySyncSingleton() {
}
public static synchronized LazySyncSingleton getInstance() {
if (null == lazySingleton) {
lazySingleton = new LazySyncSingleton();
}
return lazySingleton;
}
}
public class LazySyncSingletonTread implements Runnable {
@Override
public void run() {
LazySyncSingleton laySingleton = LazySyncSingleton.getInstance();
System.out.println(laySingleton);
}
}
双重锁校验
public class LazyDoubleCheckSyncSingleton {
private static LazyDoubleCheckSyncSingleton lazySingleton = null;
private LazyDoubleCheckSyncSingleton() {
}
public static LazyDoubleCheckSyncSingleton getInstance() {
//一层校验:为了提高性能。如果将synchronized锁在方法上或是判断条件上,当有一个线程获取到锁的时候,
// 其他线程就会处于等待状态,进入不了内部逻辑。
if (null == lazySingleton) {
synchronized (LazyDoubleCheckSyncSingleton.class) {
//第二层校验 防止两个线程同时满足了第一层校验,再做一次校验,防止多次创建
if (null == lazySingleton) {
lazySingleton = new LazyDoubleCheckSyncSingleton();
}
}
}
return lazySingleton;
}
}
public class LazyDoubleCheckSyncSingletonTread implements Runnable {
@Override
public void run() {
LazyDoubleCheckSyncSingleton laySingleton = LazyDoubleCheckSyncSingleton.getInstance();
System.out.println(laySingleton);
}
}
静态内部类
* 优点:性能最优。不需要使用线程,利用JVM加载静态内部类的机制保证多线程安全
* 懒汉式单例
* 缺点:
* 需要注意反射破坏单例的问题 解决:在构造中直接抛异常
* 需要注意序列化出现的问题 : 添加readResolve方法
public class InnerSingleton implements Serializable, Cloneable {
// private static Boolean open = true;
private InnerSingleton() {
// TODO: 设置开关这种方式不行 因为私有属性也可以被反射重新赋值
// if (open) {
// synchronized (InnerSingleton.class) {
// if (open) {
// open = false;
// }
// }
// } else {
// throw new RuntimeException("不可实例化");
// }
//被实例化后 类就被加载到内存中,不会被重复加载
if (null != InnerSingletonHandle.inner) {
throw new RuntimeException("不可实例化");
}
}
public static InnerSingleton getInstance() {
return InnerSingletonHandle.inner;
}
private static class InnerSingletonHandle {
private static final InnerSingleton inner = new InnerSingleton();
}
/**
* 解决反射问题
*
* @return
*/
public Object readResolve() {
return InnerSingletonHandle.inner;
}
/**
* 允许复制实例
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return InnerSingletonHandle.inner;
}
}
public class InnerSingletonTread implements Runnable {
@Override
public void run() {
InnerSingleton laySingleton = InnerSingleton.getInstance();
System.out.println(laySingleton);
}
}
注册式单例:枚举
public enum RegisterSingleton {
SINGLETON;
private Object object;
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
public static RegisterSingleton getInstance() {
return SINGLETON;
}
}
public class RegisterSingletonThread implements Runnable {
@Override
public void run() {
RegisterSingleton singleton = RegisterSingleton.SINGLETON;
System.out.println(singleton);
}
}
容器式单例
public class ContainerSingleton {
private ContainerSingleton() {
}
private static Map<String, Object> container = new HashMap<>();
public static Object getBean(String className) {
try {
if (!container.containsKey(className)) {
Object object = Class.forName(className).newInstance();
container.put(className, object);
return object;
}
} catch (Exception e) {
e.printStackTrace();
}
return container.get(className);
}
}
public class ContainerSingletonThread implements Runnable {
@Override
public void run() {
Object bean = ContainerSingleton.getBean("com.xy.blog.test.model.Person");
System.out.println(bean);
}
}
ThreadLocal实现单例
测试
public class SingletonTest {
/**
* 饿汉单例
*/
@Test
public void hungrySingletonTest() {
Thread t1 = new Thread(new HungrySingletonThread());
Thread t2 = new Thread(new HungrySingletonThread());
t1.start();
t2.start();
System.out.println("end");
}
/**
* 懒汉单例
*/
@Test
public void lazySingletonTest() {
Thread t1 = new Thread(new LazySingletonTread());
Thread t2 = new Thread(new LazySingletonTread());
t1.start();
t2.start();
System.out.println("end");
}
/**
* 懒汉单例 :线程安全 线程锁 锁类
*/
@Test
public void lazySyncSingletonTest() {
Thread t1 = new Thread(new LazySyncSingletonTread());
Thread t2 = new Thread(new LazySyncSingletonTread());
t1.start();
t2.start();
System.out.println("end");
}
/**
* 懒汉单例 : 方法锁 依旧线程不安全:单例被创建两次
*/
@Test
public void lazySyncSingletonTest2() {
Thread t1 = new Thread(new LazySyncSingletonTread2());
Thread t2 = new Thread(new LazySyncSingletonTread2());
t1.start();
t2.start();
System.out.println("end");
}
/**
* 懒汉单例:双重锁校验
*/
@Test
public void lazyDoubleCheckSyncSingletonTest() {
Thread t1 = new Thread(new LazyDoubleCheckSyncSingletonTread());
Thread t2 = new Thread(new LazyDoubleCheckSyncSingletonTread());
t1.start();
t2.start();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
/**
* 饿汉式 单例 静态内部类
*/
@Test
public void innerSingletonTest() {
try {
Thread t1 = new Thread(new InnerSingletonTread());
t1.start();
Thread.sleep(1);
reflect();
Thread.sleep(1);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 反射暴力获取单例
*/
@Test
public void reflect() {
try {
Class<InnerSingleton> innerSingletonClass = InnerSingleton.class;
Constructor<InnerSingleton> declaredConstructor = innerSingletonClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Field open = innerSingletonClass.getDeclaredField("open");
open.setAccessible(true);
open.set(null, true);
InnerSingleton innerSingleton = declaredConstructor.newInstance();
System.out.println(innerSingleton);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 序列化破坏单例
*/
@Test
public void serializable() {
InnerSingleton innerSingleton = InnerSingleton.getInstance();
System.out.println(innerSingleton);
InnerSingleton innerSingleton1 = JSONObject.parseObject(JSONObject.toJSONString(innerSingleton), InnerSingleton.class);
System.out.println(innerSingleton1);
try {
//序列化
FileOutputStream fileOutputStream = new FileOutputStream("temp");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(innerSingleton);
//反序列化
FileInputStream fileInputStream = new FileInputStream("temp");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
InnerSingleton o = (InnerSingleton) objectInputStream.readObject();
//打印结果
System.out.println(innerSingleton == o);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void cloneDemo() {
InnerSingleton innerSingleton = InnerSingleton.getInstance();
try {
InnerSingleton clone = (InnerSingleton) innerSingleton.clone();
System.out.println(clone == innerSingleton);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
/**
* 注册式单例
*/
@Test
public void register() {
Thread t1 = new Thread(new RegisterSingletonThread());
Thread t2 = new Thread(new RegisterSingletonThread());
t1.start();
t2.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
/**
* 注册式单例 序列化破坏单例
*/
@Test
public void registerSerializable() {
RegisterSingleton r1 = null;
RegisterSingleton r2 = RegisterSingleton.getInstance();
try {
//序列化
FileOutputStream fileOutputStream = new FileOutputStream("temp");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(r2);
//反序列化
FileInputStream fileInputStream = new FileInputStream("temp");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
r1 = (RegisterSingleton) objectInputStream.readObject();
//打印结果
System.out.println(r1 == r2);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 反射暴力获取单例
*/
@Test
public void registerReflect() {
try {
Class<RegisterSingleton> registerSingletonClass = RegisterSingleton.class;
Constructor<RegisterSingleton> declaredConstructor = registerSingletonClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
RegisterSingleton innerSingleton = declaredConstructor.newInstance();
System.out.println(innerSingleton);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 容器式 注册单例
*/
@Test
public void container() {
Thread t1 = new Thread(new ContainerSingletonThread());
Thread t2 = new Thread(new ContainerSingletonThread());
t1.start();
t2.start();
try {
Thread.sleep(5L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
// Object bean = ContainerSingleton.getBean("com.xy.blog.test.model.Person");
// System.out.println(bean);
}
}
**