/**
* 单例设计模式(单ClassLoader)
*
* 1、懒汉式:
* 线程不安全、调用效率高、可以延迟加载
* 线程安全、调用效率低、可以延迟加载(加 synchronized 线程安全)
* 2、恶汉式:
* 线程安全、调用效率高、不可以延迟加载
* 3、静态内部类:
* 线程安全、调用效率高、可以延迟加载
* 4、双重检测锁:
* 线程不安全、调用效率高、可以延迟加载
* 看似线程安全,但基于JVM内部模型,我们并不能完全控制程序执行过程
* 虽然 volatile 关键字可以解决该问题,但不兼容JDK1.5之前的版本
* 5、枚举单例:
* 线程安全、调用效率高、不可以延迟加载
* 但是缺少了普通类的一些特性,不兼容JDK1.5之前的版本
*/
public class SingletionTest1 {
public static void main(String[] args) {
MyJvm1 jvm1 = MyJvm1.getInstance();
MyJvm1 jvm1a = MyJvm1.getInstance();
MyJvm2 jvm2 = MyJvm2.getInstance();
MyJvm2 jvm2a = MyJvm2.getInstance();
MyJvm3 jvm3 = MyJvm3.getInstance();
MyJvm3 jvm3a = MyJvm3.getInstance();
MyJvm4 jvm4 = MyJvm4.getInstance();
MyJvm4 jvm4a = MyJvm4.getInstance();
MyJvm5 jvm5 = MyJvm5.instance;
MyJvm5 jvm5a = MyJvm5.instance;
System.out.println(jvm1==jvm1a);
System.out.println(jvm2==jvm2a);
System.out.println(jvm3==jvm3a);
System.out.println(jvm4==jvm4a);
System.out.println(jvm5==jvm5a);
}
/**
* 5、枚举类
*/
public enum MyJvm5{
instance;
public void doSomething(){
}
}
}
/**
* 1、懒汉式
* --> 构造私有化
* --> 声明私有静态变量
* --> 对外提供访问静态变量方法,并保证获取对象存在
*/
class MyJvm1{
private static MyJvm1 instance;
private MyJvm1(){}
public static MyJvm1 getInstance(){
if(null == instance){
instance = new MyJvm1();
}
return instance;
}
}
/**
* 2、恶汉式
* --> 构造私有化
* --> 声明私有变量,并初始化
* --> 对外提供访问静态变量方法
*/
class MyJvm2{
private static MyJvm2 instance = new MyJvm2();
private MyJvm2(){}
public static MyJvm2 getInstance(){
return instance;
}
}
/**
* 3、静态内部类
* --> 构造私有化
* --> 声明静态内部类,内部类中声明私有变量并初始化
* --> 对外提供访问 静态内部类的静态变量 的方法
*/
class MyJvm3{
private static class JVMHolder{
private static MyJvm3 instance = new MyJvm3();
}
private MyJvm3(){}
public static MyJvm3 getInstance(){
return JVMHolder.instance;
}
}
/**
* 4、双重校验
* --> 懒汉式的改进,线程安全
*/
class MyJvm4{
private static MyJvm4 instance;
private MyJvm4(){}
public static MyJvm4 getInstance(){
if(null==instance){
synchronized(MyJvm4.class){
if(null==instance){
instance = new MyJvm4();
}
}
}
return instance;
}
}
/**
* 单例 防反射、防反序列化 方法
*
* 反射:
* 在构造方法中判断实例是否为null,不为null则抛出异常阻止操作
* 序列化:
* 重写 readResolve() 返回单例
*/
public class SingletionTest2 {
public static void main(String[] args){
//单例普通获取方法
MyJvm7 jvm1 = MyJvm7.getInstance();
MyJvm7 jvm2 = MyJvm7.getInstance();
System.out.println(jvm1);
System.out.println(jvm2);
//未作处理 通过反射可以获取新的对象实例
MyJvm3 jvm3 = getOtherInstance1(MyJvm3.class);
MyJvm3 jvm4 = getOtherInstance1(MyJvm3.class);
System.out.println(jvm3);
System.out.println(jvm4);
//处理后 通过反射获取对象实例时会抛出异常
MyJvm7 jvm5 = getOtherInstance1(MyJvm7.class);
MyJvm7 jvm6 = getOtherInstance1(MyJvm7.class);
System.out.println(jvm5);
System.out.println(jvm6);
//经过 序列化-->反序列化 可以得到新的对象实例
MyJvm8 jvm7 = MyJvm8.getInstance();
MyJvm8 jvm8 = getOtherInstance2(MyJvm8.class,jvm7);
System.out.println(jvm7);
System.out.println(jvm8);
//处理后 反序列化得到的对象为单例对象
MyJvm9 jvm9 = MyJvm9.getInstance();
MyJvm9 jvm10 = getOtherInstance2(MyJvm9.class,jvm9);
System.out.println(jvm9);
System.out.println(jvm10);
}
/**
* 测试方法
* 根据反射,跳过 安全性检查(private)
* 通过构造方法实例化对象
*/
public static <T> T getOtherInstance1(Class<T> clazz){
Constructor<T> c;
T returnObj = null;
try {
c = clazz.getDeclaredConstructor();
c.setAccessible(true);
returnObj = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return returnObj;
}
/**
* 测试方法
* 通过 序列化-->反序列化 获取新的对象实例
*/
@SuppressWarnings("unchecked")
public static <T> T getOtherInstance2(Class<T> clazz,Object instance){
T returnObj = null;
try{
FileOutputStream fos = new FileOutputStream("d:/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(instance);
oos.close();
fos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
returnObj = (T) ois.readObject();
ois.close();
}catch(Exception e){
e.printStackTrace();
}
return returnObj;
}
}
class MyJvm7{
private static class JVMHolder{
private static MyJvm7 instance = new MyJvm7();
}
private MyJvm7(){
if(null!=JVMHolder.instance){
throw new RuntimeException();//阻止反射实例化对象
}
}
public static MyJvm7 getInstance(){
return JVMHolder.instance;
}
}
class MyJvm8 implements Serializable{
private static final long serialVersionUID = 1L;
private static class JVMHolder{
private static MyJvm8 instance = new MyJvm8();
}
private MyJvm8(){}
public static MyJvm8 getInstance(){
return JVMHolder.instance;
}
}
class MyJvm9 implements Serializable{
private static final long serialVersionUID = 1L;
private static class JVMHolder{
private static MyJvm9 instance = new MyJvm9();
}
private MyJvm9(){}
public static MyJvm9 getInstance(){
return JVMHolder.instance;
}
private Object readResolve() throws ObjectStreamException {
return JVMHolder.instance;//序列化返回单例对象
}
}