标签:
今天算是完完整整把老高的单例模式看了,差不多也懂了,个别不懂的再补吧,下面介绍一下5种单例模式:
饿汉式实现:线程安全,调用效率高。但是,不能延时加载。
懒汉式实现:线程安全,调用效率不高。但是,可以延时加载。
双重检测锁式:由于JVM底层内部模型原因,偶尔会出现问题,不建议使用。
静态内部类式:线程安全,调用效率高,可以延时加载。
枚举式:线程安全,调用效率高。但是,不能延时加载(避免反射和反序列化的漏洞)。
以下先介绍一下5种单例模式:
饿汉式实现:
/** *单例模式:饿汉模式 *线程安全,调用效率高。但是,不能延时加载 * * @author cookie * */ public class SingletonDemo01 { //类初始化时,立刻加载这个对象(没有延时加载的优势)。线程是天然安全 private static SingletonDemo01 instance = new SingletonDemo01(); private SingletonDemo01(){} //方法没有同步,线程安全,调用效率高。但是,不能延时加载 public static SingletonDemo01 getInstance(){ return instance; } }
懒汉式实现:
/** * 单例模式:懒汉模式 * 线程安全,调用效率不高。但是,可以延时加载 * 真正用的时候才加载,资源利用率高了。 * @author cookie * */ public class SingletonDemo02 { //类加载时,不初始化对象(延时加载:资源利用率高) private static SingletonDemo02 instance; private SingletonDemo02(){} //synchronized 防止并发量高的时候,出现多个对象 //方法同步,调用效率低, public static synchronized SingletonDemo02 getInstance(){ if(instance==null){//真正用的时候才加载 instance = new SingletonDemo02(); } return instance; } }
双重检测锁式
/** * 单例模式:双重检验锁式 结合懒汉式和饿汉式的优点,但由于JVM底层内部模型原因,偶尔会出现问题,不建议使用 * * @author cookie * */ public class SingletonDemo03 { private volatile static SingletonDemo03 instance = null; private SingletonDemo03() { } public static SingletonDemo03 getInstance() { if (instance == null) { synchronized (SingletonDemo03.class) {// 1 if (instance == null) {// 2 instance = new SingletonDemo03();// 3 } } } return instance; } }
静态内部类式
/** * 单例模式:静态内部类实现单例模式。 优点:线程安全,调用效率高,实现延时加载。 * * @author cookie * */ public class SingletonDemo04 { // 类加载时静态内部类不会加载,只有调用getInstance方法时,才会加载(实现延时加载) private static class SingletonClassInstance { private final static SingletonDemo04 instance = new SingletonDemo04(); } private SingletonDemo04() { } // 线程安全,方法不同步,调用效率提高 public static SingletonDemo04 getInstance() { return SingletonClassInstance.instance; } }
枚举式:
/** * 单例模式:枚举类型实现单例模式 线程安全,调用效率高。但是,不能延时加载 避免反射和反序列化的漏洞 * * @author cookie * */ public enum SingletonDemo05 { INSTANCE;// 这个枚举元素,本身就是单例模式 // 添加自己需要的操作 public void singletonOperation() { } }
下面是测试5种单例模式的效率:
/** * * 描述:多线程环境下五种单例模式的效率 * @author cookie */ public class Client2 { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); int threadNum = 10; final CountDownLatch countDownLatch = new CountDownLatch(threadNum); //10个线程 for (int i = 0; i < threadNum; i++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100000; i++) { SingletonDemo05 s1 = SingletonDemo05.INSTANCE; } countDownLatch.countDown();//计数器减一 } }).start(); } countDownLatch.await();//main线程阻塞,等待计数器为0,即threadNum = 0; long end = System.currentTimeMillis(); System.out.println("总耗时:"+(end-start)); } }
实现结果如下:
单例模式 | 总耗时 |
饿汉式 | 13 |
懒汉式 | 547 |
双重检测锁式 | 20 |
静态内部类式 | 17 |
枚举式 | 13 |
选用时,
单例对象,占用资源少,无需延时加载,枚举式 优于 饿汉式
单例对象,占用资源多,需要延时加载,静态内部类式 优于 懒汉式
标签:
原文地址:http://www.cnblogs.com/blogofcookie/p/5793865.html