单例模式
饿汉式单例
public class HungrySingleton {
private static final HungrySingleton HUNGRY_SINGLETON = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return HUNGRY_SINGLETON;
}
}
public class HungryStaticSingleton {
private static final HungryStaticSingleton HUNGRY_SINGLETON;
static{
HUNGRY_SINGLETON = new HungryStaticSingleton();
}
private HungryStaticSingleton(){}
public static HungryStaticSingleton getInstance(){
return HUNGRY_SINGLETON;
}
}
懒汉式单例
/**
* <p>双从检查锁定</p>
*
* @ClassName : LazySimpleSingleton
* @Author : WarrenLong
* @Date: 2020-08-23
*/
public class LazyDoubleCheckSingleton {
private static volatile LazyDoubleCheckSingleton LAZY_SIMPLE_SINGLETON;
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
if(LAZY_SIMPLE_SINGLETON == null){
synchronized (LazySimpleSingleton.class){
if(LAZY_SIMPLE_SINGLETON == null){
LAZY_SIMPLE_SINGLETON = new LazyDoubleCheckSingleton();
}
}
}
return LAZY_SIMPLE_SINGLETON;
}
}
/**
* <p>静态内部类实现单例,最强写法 </p>
*
* 没有用锁
* 懒汉
*
* @ClassName : LazyInnerClassSingleton
* @Author : WarrenLong
* @Date: 2020-08-23
*/
public class LazyInnerClassSingleton {
//虽然构造方法私有了,但是,可以进行反射
private LazyInnerClassSingleton(){
if(LazyHolder.LAZY_INNER_CLASS_SINGLETON!=null){
throw new RuntimeException("不允许构建多个实例");
}
}
//懒汉式单例
//LazyHolder里面的逻辑需要等待外部方法调用时才会执行
//巧妙利用了内部类的特性
//jvm底层的执行逻辑
public static final LazyInnerClassSingleton getInstance(){
return LazyHolder.LAZY_INNER_CLASS_SINGLETON;
}
private static final class LazyHolder{
private static final LazyInnerClassSingleton LAZY_INNER_CLASS_SINGLETON = new LazyInnerClassSingleton();
}
}
反射破坏单例
反射是可以破坏单例的,解决办法就是在无参构造方法里面抛出异常就可以了
//虽然构造方法私有了,但是,可以进行反射
private LazyInnerClassSingleton(){
if(LazyHolder.LAZY_INNER_CLASS_SINGLETON!=null){
throw new RuntimeException("不允许构建多个实例");
}
}
序列化破坏单例
序列化破坏单例,走的可不是放射的方案,构造方法抛出异常不能解决 问题,解决方法
//jdk序列化的方式,在readObject时会调用这个方法
//实际上还是创建了两次,但是在jvm层面使用readResolve返回的对象进行了覆盖
private Object readResolve(){
return HUNGRY_SINGLETON;
}
注册式单例
枚举实现单例本质上就是注册式单例
spring使用的是容器化单例,也是注册式单例的一种
/**
* <p>枚举实现单例,注册式单例</p>
*
* @ClassName : RegisterEnumSingleton
* @Author : WarrenLong
* @Date: 2020-08-23
*/
public enum RegisterEnumSingleton {
INSTANCE;
private Object data;
public static RegisterEnumSingleton getInstance(){
return INSTANCE;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
/**
* <p>注册式单例</p>
*
* @ClassName : ConainerSingleton
* @Author : WarrenLong
* @Date: 2020-08-23
*/
public class ContainerSingleton {
private ContainerSingleton(){}
public static Map<String,Object> ioc=new ConcurrentHashMap<String,Object>();
//加上双重检查锁定
public static Object getBean(String className){
if(!ioc.containsKey(className)){
Object obj=null;
try {
obj=Class.forName(className).newInstance();
ioc.put(className,obj);
}catch (Exception e){
e.printStackTrace();
}
}
return ioc.get(className);
}
}
ThreadLocal单例
线程内单例,天生线程安全
这里就不细讲了,关键字是弱引用再次gc回收,注意内存泄漏,一定要手动remove。
/**
* <p>线程单例</p>
*
* @ClassName : ThreadLocalSingleton
* @Author : WarrenLong
* @Date: 2020-08-23
*/
public class ThreadLocalSingleton {
private ThreadLocalSingleton(){}
private static final ThreadLocal<ThreadLocalSingleton> THREAD_LOCAL_SINGLETON_THREAD_LOCAL=
new ThreadLocal<ThreadLocalSingleton>(){
@Override
protected ThreadLocalSingleton initialValue() {
return new ThreadLocalSingleton();
}
};
private static ThreadLocalSingleton getInstance(){
return THREAD_LOCAL_SINGLETON_THREAD_LOCAL.get();
}
}