立即学习:https://edu.csdn.net/course/play/28941/403598?utm_source=blogtoedu
利用内部类实现懒汉式单例模式
/**
* ClassPath: LazyStaticInnerClassSingleton.class
* LazyStaticInnerClassSingleton$LazyHolder.class
* 优点:写法优雅,利用了Java本身语法特点;性能高;避免了不必要的内存的浪费
* 缺点:能够被反射机制破坏。
* */
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton(){}
public static LazyStaticInnerClassSingleton Instance(){
return LazyHolder.INSTANCE;
}
private static class LazyHolder{
private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
}
}
到此为止的单例模式都会被反射破坏。
import java.lang.reflect.Constructor;
/**
* 反射都可以拿到类的构造方法即使他是私有方法
* Declared 公开宣布的 公然的
* Accessible 可进入的,可访问的*/
public class ReflectTest {
public static void main(String[] args) {
try {
Class<?> clazz = LazyStaticInnerClassSingleton.class;
Constructor c = clazz.getDeclaredConstructor(null);
// 设置强制访问
c.setAccessible(true);
// 创建实例(破坏了单例模式)
Object instance = c.newInstance();
Object in = c.newInstance();
System.out.println(instance);
System.out.println(in);
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* ClassPath: LazyStaticInnerClassSingleton.class
* LazyStaticInnerClassSingleton$LazyHolder.class
* 优点:利用了Java本身语法特点;性能高;避免了不必要的内存的浪费; 不能够被反射机制破坏。
* 缺点:写法不优雅,
* */
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton(){
if (LazyHolder.INSTANCE != null)
throw new RuntimeException("不允许非法访问");
}
public static LazyStaticInnerClassSingleton Instance(){
return LazyHolder.INSTANCE;
}
private static class LazyHolder{
private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
}
}
注册式单例——将每一个实例都缓存到统一的容器中,使用唯一标识获取实例。
public enum EnumSingleton {
INSTANCE;
private Object data;
public void setData(Object data){
this.data = data;
}
public Object getData(){
return data;
}
public static EnumSingleton getInstance(){
return INSTANCE;
}
}
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 线程不安全
* */
public class ContainerSingleton {
private ContainerSingleton(){}
private static Map<String, Object> ioc = new ConcurrentHashMap<>();
public static Object getInstance(String className){
Object instance = null;
if (!ioc.containsKey(className)){
try {
instance = Class.forName(className).newInstance();
ioc.put(className, instance);
} catch (Exception e) {
e.printStackTrace();
}
//return ioc.get(className);
return instance;
}else {
return ioc.get(className);
}
}
}
序列化:
把内存中对象的状态转化为字节码的形式;
把字节码通过IO输出流写到磁盘上;
内存对象状态就可以永久保存下来了;——持久化。
反序列化:
将持久化的字节码内容,通过IO输入流读到内存中来,转化成一个Java对象。
ThreadLocal单例——保证线程内部的全局唯一,且天生线程安全。
public class ThreadLocalSingleton {
private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance = new ThreadLocal<ThreadLocalSingleton>(){
@Override
protected ThreadLocalSingleton initialValue() {
return new ThreadLocalSingleton();
}
};
private ThreadLocalSingleton(){}
public static ThreadLocalSingleton getInstance(){
return threadLocalInstance.get();
}
}
单例模式的优点:
在内存中只有一个实例,减少了内存开销。
可以避免对资源的多重占用
设置全局访问点,严格控制访问
单例模式的缺点:
没有接口,扩展困难
如果要扩展单例对象,只有修改代码,没有其他途径。
总结:
1.私有化构造器
2.保证线程安全
3.延迟加载
4.防止序列化和反序列化破坏单例
5.防御反射攻击单例。