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

原创 2018年04月15日 21:12:11

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

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的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ljm15832631631/article/details/79953347

单例模式的五种实现方式

单例模式可以说是23中设计模式中应用最广的一种模式了。        定义:确保某一个类只有一个实例,自行实例化并且想整个系统提供这个实例。       使用场景:避免某个类产生多个对象而消耗过多...
  • soul_code
  • soul_code
  • 2015年12月05日 09:53
  • 10159

java单例模式五种实现方式

应用场景由于单例模式只生成一个实例, 减少了系统性能开销(如: 当一个对象的产生需要比较多的资源时, 如读取配置, 产生其他依赖对象, 则可以通过在应用启动时直接产生一个单例对象, 然后永久驻留内存的...
  • JQ_AK47
  • JQ_AK47
  • 2017年02月06日 17:03
  • 4925

常用的五种单例模式实现方式

单例模式的关键点1) 构造方法不对外开放,为private2) 确保单例类只有一个对象,尤其是多线程模式下3) 通过静态方法或枚举返回单例对象4) 确保单例类在反序列化是不会重新创建新的对象 单例模式...
  • username987654
  • username987654
  • 2018年01月15日 18:44
  • 22

单例模式5种实现方式

在github上看到一个项目,实现了多种设计模式,就把它fork下来,一个一个看,然后也可以学习参考别人写的代码。 地址:https://github.com/iluwatar/java-desig...
  • FoolishAndStupid
  • FoolishAndStupid
  • 2016年04月24日 10:13
  • 4148

单例模式的解读以及和全局变量的区别

单例模式分为三种:(1)、懒汉式单例; (2)、饿汉式单例; (3)、登记式单例 单例模式的三个特点:(1)单例类只有一个实例; (2)、单...
  • Warpar
  • Warpar
  • 2017年07月11日 09:20
  • 1160

单例模式跟全局变量相比的好处

全局变量是最容易引起初学者兴趣的了,在整个项目中,任何一个函数,每一行代码都可以轻易访问所有的全局变量,并且可以不用付出额外的代价,全局变量看起来就像是为懒惰的程序员设计的一条绿色通道,如果不想看到函...
  • ozdazm
  • ozdazm
  • 2013年01月24日 14:26
  • 4893

五种单例模式的效率问题

谈到效率,当然要使用多线程!5个单例设计模式同时创建1亿个单例的耗时。...
  • a445849497
  • a445849497
  • 2017年02月26日 23:02
  • 263

单例模式和全局变量

单例模式和全局变量【转】 全局变量是最容易引起初学者兴趣的了,在整个项目中,任何一个函数,每一行代码都可以轻易访问所有的全局变量,并且可以不用付出额外的代价,全局变量看起来就像是为懒惰的程序员设...
  • Ashelyhss
  • Ashelyhss
  • 2013年09月03日 21:12
  • 4948

几种常用单例模式

1.普通单例 public class PanalCtrl : MonoBehaviour { private static PanalCtrl _instance; public sta...
  • Sam_ONE
  • Sam_ONE
  • 2017年01月11日 20:54
  • 329

单例模式之序列化与反序列化实现

静态内部类可以达到线程安全问题,但是如果遇到序列化对象时,使用默认的方式运行得到的结果 坑你还是多例的。 package test; import java.io.ObjectStreamExc...
  • anLA_
  • anLA_
  • 2017年04月16日 13:38
  • 868
收藏助手
不良信息举报
您举报文章:单例模式的五种实现与比较
举报原因:
原因补充:

(最多只允许输入30个字)