标签:常见 构造 code 初始 row 过程 自定义 允许 hung
public class SingletonHungry {
// 1.构造器私有化,避免外部直接创建对象
private SingletonHungry() {}
// 2.创建一个静态实例,类初始化时立即加载这个对象(类加载的过程默认是线程安全的(JVM))
private static SingletonHungry instance = new SingletonHungry();
// 3.创建一个对外的公共的静态方法访问该变量,方法没有同步,效率较高
public static SingletonHungry getInstance() {
return instance;
}
}
public class Singleton {
// 1.构造器私有化,避免外部直接创建对象
private Singleton() {}
// 2.创建一个静态引用
private static Singleton instance = null;
// 3.创建一个对外的公共的静态方法访问该变量,如果变量没有对象,则创建一个,需要同步,效率较低
// 简单实现1
public static synchronized Singleton getInstance() {
if(null == instance) {
instance = new Singleton();
}
return instance;
}
// 双重检测锁实现2(有问题,不建议):Thread, double checking
public static Singleton getInstance2() {
if(null == instance) {
synchronized (Singleton.class) {
if (null == instance) {
instance = new Singleton();
}
}
}
return instance;
}
}
兼备了高效并发调用与延迟加载的优点
public class Singleton {
private Singleton() {}
private static class Inner {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return Inner.instance;
}
}
public enum SingletonEnum {
// 定义一个枚举元素,代表一个实例
INSTANCE;
// 可以有自定义操作
public void operate() {}
}
/**
* 测试使用反射构造对象
*/
private static void testReflect() throws Exception {
SingletonLazy s1 = SingletonLazy.getInstance();
SingletonLazy s2 = SingletonLazy.getInstance();
System.out.println(s1 == s2);
// 利用反射获取Singleton的Class
Class<SingletonLazy> clazz = (Class<SingletonLazy>) Class.forName("singleton.SingletonLazy");
// 获取Singleton类中的构造方法
Constructor<SingletonLazy> constructor = clazz.getDeclaredConstructor();
// 设置访问权限,允许访问私有属性
constructor.setAccessible(true);
SingletonLazy s3 = constructor.newInstance();
SingletonLazy s4 = constructor.newInstance();
System.out.println(s3 == s4);
}
// 防止操作:在单例类的私有构造器中添加对象不为空的处理操作,如抛出异常等
private SingletonLazy() {
if (instance != null) {
throw new RuntimeException("构造器私有了,你哪来的对象?");
}
}
/**
* 测试使用反序列化构造对象
*/
private static void testSerializ() throws Exception {
SingletonLazy s1 = SingletonLazy.getInstance();
// 输出流
FileOutputStream fis = new FileOutputStream("src/singleton/a.txt");
ObjectOutputStream oos = new ObjectOutputStream(fis);
oos.writeObject(s1);
oos.close();
// 输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/singleton/a.txt"));
SingletonLazy s3 = (SingletonLazy) ois.readObject();
ois.close();
System.out.println(s1 == s3);
}
/**
* 防止操作:反序列化时,在单例类中定义 Object readResolve() 方法并指定返回对象,
* 则通过输入输出流获取对象时直接调用此方法以防止获取不同的对象(实际是回调)
*/
private Object readResolve() {
return instance;
}
private static void testEfficiency() throws InterruptedException {
long start = System.currentTimeMillis();
// 使用 CountDownLatch 监控线程的执行状态
CountDownLatch countDownLatch = new CountDownLatch(10);
// 多线程开始执行
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 100000; i++) {
// Object o = SingletonHungry.getInstance(); //15ms
// Object o = SingletonLazy.getInstance(); //65ms
// Object o = SingletonInner.getInstance(); //47ms
Object o = SingletonEnum.INSTANCE; //16ms
}
// 执行完一个线程,将总线程数量 -1
countDownLatch.countDown();
}
}).start();
}
// 阻塞当前线程(main),直到计数器变为0才会继续向下执行
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("总耗时:" + (end - start) + "ms");
}
标签:常见 构造 code 初始 row 过程 自定义 允许 hung
原文地址:https://www.cnblogs.com/mabaoqing/p/10691640.html