单例模式

核心作用:

  保证一个类只有一个对象,并且提供一个访问该实例的全局访问点。

常见应用场景:

  1、windows中的任务管理器就是典型的单例模式

  2、windows回收站也是单例模式

  3、项目中读取配置文件的类也是单例模式

  4、日志管理

  。。。

单例模式的优点:

  1、由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其它依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决

  2、单例模式可以设置全局访问点,优化共享资源的访问,例如可以设计一个单例类,负责所有数据表的映射处理

 

常见的五种单例模式实现方式:

  主要:

    饿汉式:(线程安全,调用效率高。但是不能延时加载)

    懒汉式:(线程安全,调用效率不高。但是可以延时加载)

  其他:

    双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)

    静态内部类式(线程安全、调用效率高。但是可以延时加载)

    枚举单例(线程安全、调用效率高。不能延时加载)

饿汉式

package com.pattern.singleton;

/**
 * 测试饿汉单例模式
 */
public class SingLetonDemo1 {

	//类初始化立即加载,所以叫饿汉式
	//类初始化时,立即加载这个对象(不能延时加载),加载类时,天然的是线程安全的
	private final static SingLetonDemo1 singLetonDemo1 = new SingLetonDemo1();
	
	private SingLetonDemo1() {
	}
	
	//方法没有同步,调用效率高
	public static SingLetonDemo1 getInstance() {
		return singLetonDemo1;
	}
	
}

懒汉式  

package com.pattern.singleton;

/**
 * 测试懒汉单例模式
 */
public class SingLetonDemo2 {
	
	//类初始化时,不初始化这个对象(延时加载,真正用的时候加载)
	private static SingLetonDemo2 singLetonDemo2 = null;
	
	private SingLetonDemo2() {
	}
	
	//方法同步调用效率低
	public static synchronized SingLetonDemo2 getInstance() {
		if(singLetonDemo2 == null) {
			singLetonDemo2 = new SingLetonDemo2();
		}
		return singLetonDemo2;
	}

}

双重检测锁模式

这个模式将同步内容放到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才进行同步创建了以后就没必要了。

 

package com.sjms.singleton;

public class SingletonDemo3 {
	
	public static SingletonDemo3 instance = null;
	
	public static SingletonDemo3 getInstance() {
		if(instance == null) {
			SingletonDemo3 sc;
			synchronized (SingletonDemo3.class) {
				sc = instance;
				if(sc == null) {
					synchronized (SingletonDemo3.class) {
						sc = new SingletonDemo3();
					}
				}
				instance = sc;
			}
		}
		return instance;
	}
	
}

 问题:由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用。

静态类实现方式(也是一种懒汉加载方式)

package com.sjms.singleton;

public class SingletonDemo4 {
	
	private SingletonDemo4() {
	}
	
	private static class SingletonClassInstance{
		public static final SingletonDemo4 instance = new SingletonDemo4();
	}
	
	public static SingletonDemo4 getInstance() {
		return SingletonClassInstance.instance;
	}
	
}

 要点:

  外部类没有static属性,则不会像恶汉式那样立即加载对象

  只有真正调用getInsatnce函数的时候,才会加载静态内部类。加载类时,线程是安全的。instance是static final 类型,保证了内存中只有这样一个类型实例存在,从而保证了线程的安全性

  兼并了并发高效调用和延时加载的优势。

 

枚举实现方式:

  

public enum SingletonDemo5 {
	
	instace;
	
	public static void doSomething() {
		
	}
	
}

 

优点:实现简单

      枚举本身就是单例模式。由jvm从根本上提供保障!避免通过反射和反序列化的漏洞~

缺点:无延迟加载

 

总结:

  主要:饿汉式 (线程安全,调用效率高,但是不能延时加载)

     懒汉式 (线程安全,调用效率不高,但是能延时加载)

  其它:双重检测锁式(由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用)

     静态内部类式(线程安全,调用效率高,可以延时加载)

     枚举式(线程安全,调用效率高,不可以延时加载)

 

如何选用:

    单例对象占用资源少,不需要演示加载 (枚举式好于饿汉式)

    单例对象占用资源大,需要延时加载(静态内部类好于懒汉式)

  

 

 

 

 

  

 

posted @ 2017-12-16 01:20  jianhuazhao  阅读(180)  评论(0编辑  收藏  举报