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

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

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 = AAAAAA
paramB = BBBBBB

五种方法的比较

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

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

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

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

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

猜你喜欢

转载自blog.csdn.net/ljm15832631631/article/details/79953347