package com.bjsxt.cn.singleton;
import java.io.ObjectStreamException; import java.io.Serializable;
/** * 2015年3月26日22:14:22 * 懒汉式单例模式 * 该懒汉式的特点是: * 1, 构造器私有 * 2, 私有静态属性,类型为该类的对象,但是在声明时并没有初始化。因为Lazy load。因为懒惰 * 3, 静态访问私有的那个静态属性的静态方法。但是在该方法体中先要检查该静态属性是否为空,为空则new,否则直接返回 * 测试如何防止反射和反序列化破坏单例模式的有效性 * @author wanna * */ public class SingletonDemo6 implements Serializable{ private SingletonDemo6() { if (instance != null) { throw new RuntimeException(); } } private static SingletonDemo6 instance; //因为该方法加了同步synchronized,效率低,但是具有延时加载的能力。提高了资源的利用率 public static synchronized SingletonDemo6 getInstance() { if (instance == null) { instance = new SingletonDemo6(); } return instance; } //反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象! public Object readResolve() throws ObjectStreamException{ return instance; } }
package com.bjsxt.cn.singleton;
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.lang.reflect.Constructor;
public class client { public static void main(String[] args)throws Exception { SingletonDemo6 s1 = SingletonDemo6.getInstance(); SingletonDemo6 s2 = SingletonDemo6.getInstance(); System.out.println(s1); System.out.println(s2); //通过反射调用私有构造器。 //这种问题通过在SingletonDemo6私有构造器中判断,如果要new对象,就报异常 /* Class<SingletonDemo6> clazz = (Class<SingletonDemo6>) Class.forName("com.bjsxt.cn.singleton.SingletonDemo6"); Constructor<SingletonDemo6> constructor = clazz.getDeclaredConstructor(null); constructor.setAccessible(true); SingletonDemo6 s3 = constructor.newInstance(); SingletonDemo6 s4 = constructor.newInstance(); System.out.println(s3); System.out.println(s4); */ //通过反序列化破坏单例 //为了防止反序列化破坏单例,可以在SingletonDemo6类中定义方法readResolve() /* * //反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象! public Object readResolve() throws ObjectStreamException{ return instance; } * * */ FileOutputStream fos = new FileOutputStream("D:/a.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(s1); oos.close(); fos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/a.txt")); SingletonDemo6 s5 = (SingletonDemo6) ois.readObject(); System.out.println(s5); } } /*使用反射破坏单例模式运行结果 * com.bjsxt.cn.singleton.SingletonDemo6@659e0bfd com.bjsxt.cn.singleton.SingletonDemo6@659e0bfd com.bjsxt.cn.singleton.SingletonDemo6@2a139a55 com.bjsxt.cn.singleton.SingletonDemo6@15db9742 * * 使用反序列化破坏单例模式结果 * com.bjsxt.cn.singleton.SingletonDemo6@659e0bfd com.bjsxt.cn.singleton.SingletonDemo6@659e0bfd com.bjsxt.cn.singleton.SingletonDemo6@5c647e05 * * */
package com.bjsxt.cn.singleton;
import java.util.concurrent.CountDownLatch; /* * 2015年3月26日22:14:11 * 测试多线程模式下五种单例模式的执行效率 * CountDownLatch * A synchronization aid that allows one or more threads * to wait until a set of operations being performed in other threads completes. * * */ public class client2 { public static void main(String[] args) throws Exception{ int threadNum = 10; CountDownLatch count = new CountDownLatch(threadNum); long start = System.currentTimeMillis(); for (int i=0; i<threadNum; i++) { new Thread(new Runnable() { @Override public void run() { for (int i=0; i<1000000; i++) { Object o = SingletonDemo1.getInstance(); // Object o = SingletonDemo5.Instance; } count.countDown(); } }).start(); } count.await(); long end = System.currentTimeMillis(); System.out.println("总耗时 " + (end - start)); } }