当前位置: 移动技术网 > IT编程>软件设计>设计模式 > JAVA设计模式——单例模式

JAVA设计模式——单例模式

2018年11月20日  | 移动技术网IT编程  | 我要评论

英文名:singleton pattern。英文原话:ensure a class has only one instance,and provide a global point of access to it。

单例模式的主要作用是确保一个类只有一个实例。

一、实现方式

1.静态内部类

这是最好的实现方式,废话不多说,直接上代码。

要点:私有的构造方法,保证外界无法直接实例化。一个内部静态类来进行实例化,这样能达到延迟初始化的效果。并且有 classloader 机制来保证初始化 instance 时只有一个线程。

public class singleton {
    //构造方法私有,保证外界无法直接实例化
    private singleton(){}

    public static singleton getinstance(){
        return singletoninstance.instance;
    }

    private static class singletoninstance{
        static singleton instance = new singleton();
    }
}

2.饿汉模式

public class hungrysingleton {
    private hungrysingleton() {}

    private static hungrysingleton instance = new hungrysingleton();

    private static hungrysingleton getinstance() {
        return instance;
    }
}

饿汉模式是在类加载的时候,就进行对象实例化。缺点就是如果这个类里面有一个静态方法,代码里先使用了这个静态方法,这时候就会完成实例化。这时候可能是还用不到这个实例的,就会造成浪费。就这一个问题,所以结合具体情况,饿汉模式使用也没有大问题。

3.懒汉模式

public class lazysingleton {
    private static lazysingleton instance;

    private lazysingleton() {
    }

    public static lazysingleton getinstance() {
        if (instance == null) {
            instance = new lazysingleton();
        }
        return instance;
    }
}

懒汉模式是在第一次引用类时,才进行对象实例化。这种方式存在的问题是线程安全问题,就是多个线程同时去获取实例的时候,可能会产生多个实例。

讲到线程安全问题,通常就会想到synchronized加一个锁来保证线程安全问题,没错,如下图,可以这样来保证线程安全

public class onechecklazysingleton {
    private static onechecklazysingleton instance;

    private onechecklazysingleton() {
    }

    public static synchronized onechecklazysingleton getinstance() {
        if (instance == null) {
            instance = new onechecklazysingleton();
        }
        return instance;
    }
}

但是这样每次去获取实例的时候,都会去走一遍这个锁,其实在实例已经创建过后,就不会有线程安全问题了。所以有了改进版,双重检查锁,如下

public class doublechecklazysingleton {
    private volatile static doublechecklazysingleton singleton;

    private doublechecklazysingleton() {
    }

    public static doublechecklazysingleton getsingleton() {
        if (singleton == null) {
            synchronized (singleton.class) {
                if (singleton == null) {
                    singleton = new doublechecklazysingleton();
                }
            }
        }
        return singleton;
    }
}

这样在实例已经创建后,再去获取就不会走锁了。注意这里的volatile关键字,volatile禁止了jvm自动的指令重排序优化,是在jdk1.5及以后才有的。这样,这种方式也是没有问题的了,就是代码相对复杂。

二、具体应用

先讲一个概念,有状态的类和无状态的类。

有状态的类:类里面有成员变量,而且成员变量是会变的。

无状态的类:类里面没有成员变量,或者有成员变量但是不可变的。

 

无状态的类才适合使用单例模式,一些连接池,比如连接redis的jedis工具的jedispool 可以使用单例。

 

再讲一下分布式下的情况,分布式时,就是有多个jvm。一开始想到这个问题时,我还认为在分布式情况下会有问题,因为在一个jvm下有一个单例,整个系统不是只有一个实例了。 但仔细想了一下,因为是无状态的类,对整个系统是没有问题的。

 

好了,差不多就这些。谢谢阅读~

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网