首页 > 学院 > 开发设计 > 正文

单例模式的五种实现与比较

2019-11-06 08:16:56
字体:
来源:转载
供稿:网友

一、懒汉式实现单例模式读取配置文件

import java.io.IOException;import java.io.InputStream;import java.util.PRoperties;//懒汉式public class Singleton1 {	/**	 * 定义一个类变量用来存放创建好的类实例	 */	private static  Singleton1 uniqueInstance = null;	/**	 * 用来存放配置文件的参数paramA的值	 */	private String paramA;	/**	 * 用来存放配置文件的参数paramB的值	 */	private String paramB;		//返回参数paramA的值	public String getParamA() {		return paramA;	}	//返回参数paramB的值	public String getParamB() {		return paramB;	}	/**	 * 私有化构造方法	 */	private Singleton1(){		readConfig();	}	/**	 * 读取配置文件,把读取的信息设置到属性上	 */	private void readConfig() {		Properties p = new Properties();		InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");		try {			p.load(in);		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		this.paramA = p.getProperty("paramA");		this.paramB = p.getProperty("paramB");	}	/**	 * 定义一个方法来为客户端提供Singleton1类实例	 * @return 一个Singleton1类实例	 */	public static Singleton1 getSingleton1Instance(){		if(uniqueInstance == null){			uniqueInstance = new Singleton1();			return uniqueInstance;		}				return uniqueInstance;	}}

二、饿汉式实现单例模式读取配置文件

import java.io.IOException;import java.io.InputStream;import java.util.Properties;//饿汉式public class Singleton2 {	/**	 * 定义一个类变量用来存放创建好的类实例	 */	private static  Singleton2 uniqueInstance = new Singleton2();	/**	 * 用来存放配置文件的参数paramA的值	 */	private String paramA;	/**	 * 用来存放配置文件的参数paramB的值	 */	private String paramB;		//返回参数paramA的值	public String getParamA() {		return paramA;	}	//返回参数paramB的值	public String getParamB() {		return paramB;	}	/**	 * 私有化构造方法	 */	private Singleton2(){		readConfig();	}	/**	 * 定义一个方法来为客户端提供Singleton2类实例	 * @return 一个Singleton2类实例	 */	public static Singleton2 getSingleton2Instance(){		return uniqueInstance;	}	/**	 * 读取配置文件,把读取的信息设置到属性上	 */	private void readConfig() {		Properties p = new Properties();		InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");		try {			p.load(in);		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		this.paramA = p.getProperty("paramA");		this.paramB = p.getProperty("paramB");	}}

三、缓存实现单例模式

import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Map;import java.util.Properties;//用缓存来实现单例模式public class Singleton3 {	/**	 * 定义一个默认的key值	 */	private final static String DEFAULT_KEY ="one";	/**	 * 缓存实例的容器	 */	private static  Map<String,Object> map = new HashMap<String,Object>();		/**	 * 用来存放配置文件的参数paramA的值	 */	private String paramA;	/**	 * 用来存放配置文件的参数paramB的值	 */	private String paramB;		//返回参数paramA的值	public String getParamA() {		return paramA;	}	//返回参数paramB的值	public String getParamB() {		return paramB;	}	/**	 * 构造方法私有化	 */	private Singleton3(){		readConfig();	}	/**	 * 定义一个方法来为客户端提供Singleton3类实例	 * @return 一个Singleton3类实例	 */	public static Singleton3 getSingleton3Instance(){		Singleton3 instance = (Singleton3) map.get("one");		if(instance==null){			instance = new Singleton3();			map.put(DEFAULT_KEY, instance);		}		return instance;	}	/**	 * 读取配置文件,把读取的信息设置到属性上	 */	private void readConfig() {		Properties p = new Properties();		InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");		try {			p.load(in);		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		this.paramA = p.getProperty("paramA");		this.paramB = p.getProperty("paramB");	}}四、通过双重检查加锁的方式实现单例模式

import java.io.IOException;import java.io.InputStream;import java.util.Properties;//通过双重检查加锁的方式实现单例模式public class Singleton4 {	/**	 * 用来存放配置文件的参数paramA的值	 */	private String paramA;	/**	 * 用来存放配置文件的参数paramB的值	 */	private String paramB;		//返回参数paramA的值	public String getParamA() {		return paramA;	}	//返回参数paramB的值	public String getParamB() {		return paramB;	}	/**	 * 构造方法私有化	 */	private Singleton4(){		readConfig();	}	/**	 * 保存实例变量添加volatile关键词修饰	 */	private volatile static Singleton4 uniqueInstance = null;	/**	 * 读取配置文件,把读取的信息设置到属性上	 */	private void readConfig() {		Properties p = new Properties();		InputStream in = Singleton4.class.getResourceAsStream("AppConfig.properties");		try {			p.load(in);		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		this.paramA = p.getProperty("paramA");		this.paramB = p.getProperty("paramB");	}	/**	 * 定义一个方法来为客户端提供Singleton4类实例	 * @return 一个Singleton4类实例	 */	public static Singleton4 getSingleton4Instance(){		//先检查实例是否存在,如果不存在才进入下面的同步快		if(uniqueInstance == null){			//同步块,线程安全的创建实例对象			synchronized (Singleton4.class){				uniqueInstance = new Singleton4();				return uniqueInstance;			}		}				return uniqueInstance;	}}	五、通过JVM保证线程安全的方式实现单例模式(高人的方法)

import java.io.IOException;import java.io.InputStream;import java.util.Properties;//通过JVM保证线程安全性public class Singleton5 {		private String paramA;		private String paramB;	public String getParamA() {		return paramA;	}	public String getParamB() {		return paramB;	}		private static class SingletonHolder{		private static Singleton5 instance = new Singleton5();	}		public static Singleton5 getSingleton5Instance(){		return SingletonHolder.instance;	}		private Singleton5(){		readConfig();	}		private void readConfig() {		Properties p = new Properties();		InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");		try {			p.load(in);		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		this.paramA = p.getProperty("paramA");		this.paramB = p.getProperty("paramB");	}}下面是本文所使用的配置文件:

AppConfig.properties

内容为:

paramA = AAAAAAparamB = BBBBBB

五种方法的比较

第一种方法,是以时间换空间,实现了延迟加载,但线程不安全;

第二种方法,是以空间换时间,没有实现延迟加载,线程安全;

第三种方法,与第一种方法相比,由于是通过缓存,所以效率大大提高,但同样是线程不安全的;

第四种方法,实现了延迟加载和线程安全,使用双重检查加锁的方法,使得性能不会有太大的影响,但会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高;

第五种方法:高人的方法,这个解决方案被称为Lazy initialization holder class模式,这个模式综合使用了java的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表