设计模式之单例模式

单例模式

1.单例模式定义:保证一个类只有一个实例,并且提供他一个全局的访问点。

2.单例模式功能:用来保证这个类在运行期间只会创建出一个类实例,并提供一个全局的唯一访问这个类实例的访问点。

3.单例模式的范围:是一个ClassLoader及其子类ClassLoaer的范围。

4.单例模式的命名:一般建议单例模式的方法命名为getInstance();

5.饿汉式单例模式:

public class Account {
    //定义一个变量来存储创建好的实例,直接在这里创建实例,只会创建一次。
    private static Account intance = new Account();
    /**
     * 私有化构造方法,好在内部控制创建实例的数目
     */
    private Account(){
    }
    
    /**
     * 定义一个方法微客户端提供类实例
     */
    public static Account getIntance(){
        //直接使用已创建好的实例
        return intance;
    }
}

 

上面的例子中,在这个类被加载时,静态变量instance会被初始化,此时类的私有构造子会被调用。这时候,单例类的唯一实例就被创建出来了。

饿汉式其实是一种比较形象的称谓。既然饿,那么在创建对象实例的时候就比较着急,饿了嘛,于是在装载类的时候就创建对象实例。

饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。

6.懒汉式单例模式:

/**
 * 懒汉式
 *
 */
public class Account2 {    
    /**
     * 定义一个变量来存储创建好的实例
     * 
     */
    private static Account2 instance = null;
    /**
     * 私有构造方法
     */
    private Account2(){
        
    }
    /**
     * 定义一方法为客户端创建实例
     * 
     */
    public static synchronized Account2 getInstance(){
        //判断存储的类的实例是否有值
        if(instance == null){
            //如果没有。就创建一个实例,并赋值
            instance = new Account2();
        }
        return instance;
    }

7.读取应用配置文件,单例模式实现

/**
 * 读取应用配置文件,单例模式实现
 *
 */
public class AppConfig {
    /**
     * 定义一个变量来存储创建好的实例,直接在这里创建类实例,只会创建一次。
     * 
     */
    private static AppConfig instance = new AppConfig();

    /**
     * 定义一个方法来为客户端提供Appconfig 的实例。
     */
    public static AppConfig getIntance() {
        return instance;
    }

    /**
     * 用来存放配置文件中参数user的值
     */
    private String user;

    public String getUser() {
        return user;
    }

    /**
     * 用来存放配置文件中参数pass的值
     */
    private String pass;

    public String getPass() {
        return pass;
    }

    private AppConfig() {
        // 读取配置文件的方法
        readConfig();
    }

    private void readConfig() {
        Properties p = new Properties();
        InputStream in = AppConfig.class.getResourceAsStream("Appconfig.properties");
        try {
            System.out.println("现在读取配置文件一次***************");
            p.load(in);
            // 把配置文件读出来的内容设置到属性上
            this.user = p.getProperty("user");
            this.pass = p.getProperty("pass");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("出错了");
            e.printStackTrace();
        }
    }
}

public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            AppConfig config = AppConfig.getIntance();
            System.out.println(i+"user位:"+config.getUser()+"密码"+config.getPass());
        }
    }
}

总结:

 1.饿汉式是线程安全的

 2.如何实现懒汉式的线程安全

   加上synchronize即可

 3.双重检查加锁:

所谓双重检查加锁指的是,并不是每次进入getIntance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在。如果不存在才会进入下面的同步块,进入同步块再次检查实例是否存在。如果不存在,就在同步的情况下创建一个实例,这是第二重检查,这样一来只需要同步一次了,从而减少了多次在同步情况下判断所浪费的时间。

双重检查加锁的实现会使用一个关键字volatile,他的意思是被volatile修饰的变量值将不会被本地线程缓存,所有对该变量的读写都是操作共享内存,从而保证了多线程能正确的处理该变量。

 

posted @ 2017-07-25 17:12  逆风H2O2  阅读(115)  评论(0编辑  收藏  举报