一、懒汉式实现单例模式读取配置文件
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的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。
新闻热点
疑难解答