单例设计模式
/** 单例设计模式
*
*/
public class SimpleModelController {
/** 饿汉式单利模式 类只被创建一次,所有调用此方法的共享一个类
** 类被初始化的时候 单利类被加载出来
*/
private static SimpleModelController con = new SimpleModelController();
private SimpleModelController(){}
public static SimpleModelController getInstance(){
return con;
}
/**
* 懒汉是单例模式 类有可能被创建多次 但是加上 同步的关键词之后,同步执行方法,同样可避免创建多次类
* 类被初始化的时候类不加载 ,调用方法的时候加载类;
*/
private static SimpleModelController lazysimpleModelController;
private SimpleModelController(){} TODO
public static synchronized SimpleModelController getLazyInstance(){
if (null == lazysimpleModelController) {
lazysimpleModelController = new SimpleModelController();
}
return lazysimpleModelController;
}
/**
* 双重判定锁
* 假设有100个线程 双重判定锁会同事执行,而上面懒加载的话 会等待方法执行完毕再进入方法
* 双重判定算的话,会进入方法 100个线程可以同时判断if 理论只有一个判断时间
* 如果面对高并发的话 选择双重判定锁
* volatile 这个关键字 是java1.5 语义禁止指令 重排序优化
* (双重判定锁 也会出现失败)
* 在jvm初始化的 会给该对象分配一个内存空间,并且把对象的字段设置成默认值,此时的时候就把当前这个inser
* 对象分配到一个默认的地址,此时刚好有一个线程来进行调用getDualInstance方法,取到的就是不正确的对象
* 加上volatile关键字之后 会按照执行顺序执行,等待当前对象初始化完成
*/
private static SimpleModelController inser = null;
private static volatile SimpleModelController inser = null;
private SimpleModelController(){ } TODO
public static SimpleModelController getDualInstance(){
if (inser == null) {
synchronized (SimpleModelController.class){
if (inser == null) {
inser = new SimpleModelController();
}
}
}
return inser;
}
/**
* 利用java 反射 创建多个单利对象
* 这里每次运行都会创建心的单利对象,违背了单利模式的原则 不要使用反射产生单利对象
*
*/
public static void reflect(){
try {
Class c= Class.forName(SimpleModelController.class.getName());
Constructor declaredConstructors = c.getDeclaredConstructor();
declaredConstructors.setAccessible(true);
SimpleModelController simpleModelController = (SimpleModelController)c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//
最后一个方法使用反射机制实现了 创建多个单例,对于getDeclaredConstructor 不是太理解 进行了检索;
java 反射使用了getDeclaredConstructor方法,
******** getConstructor()和getDeclaredConstructor()区别:********
getDeclaredConstructor(Class<?>… parameterTypes) 这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
再来看getConstructor(Class<?>… parameterTypes)
这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器。
getConstructors()的返回结果同样也没有参数类型的过滤。
/**
* 利用静态内部类 来实现lazy 同时也能保证线程安全
*/
private static class simpleHerder{
public static SimpleModelController model = new SimpleModelController();
}
private SimpleModelController(){}
public static SimpleModelController conn(){
return simpleHerder.model;
}
这种方式同样利用了类加载机制来保证只创建一个instance实例。它与饿汉模式一样,也是利用了类加载机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。