设计模式part3
单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例
常见的单例模式可以分为懒汉模式和饿汉模式
懒汉模式
懒汉模式是指在第一次调用的时候进行实例化
【java】
publicclass Singleton1 {
//私有的构造器可以在其他类中实例化被实例化
private Singleton1(){}
privatestatic Singleton1 singleton1 = null;
publicstatic Singleton1 getInstance(){
//第一次调用的时候实例化
if(singleton1==null){
singleton1 = new Singleton1();
}
returnsingleton1;
}
}
然而这种方式会存在线程安全的问题,在多线程并发的情况下会出现问题,于是可以有一下方式进行优化
一、【java】
publicstaticsynchronized Singleton1 getInstance(){
//第一次调用的时候实例化
if(singleton1==null){
singleton1 = new Singleton1();
}
returnsingleton1;
}
synchronized关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,所以,这个地方需要改进。我们改成下面这个:
二、【java】
publicstatic Singleton1 getInstance() {
if (singleton1 == null) {
synchronized (singleton1) {
if (singleton1 == null) {
singleton1 = new Singleton1();
}
}
}
returnsingleton1;
}
似乎解决了之前提到的问题,将synchronized关键字加在了内部,也就是说当调用的时候是不需要加锁的,只有在instance为null,并创建对象的时候才需要加锁,性能有一定的提升。但是,这样的情况,还是有可能有问题的,看下面的情况:在Java指令中创建对象和赋值操作是分开进行的,也就是说instance= new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了
publicclass Singleton2 {
privatestaticclass SingletonFactory {
privatestaticfinal Singleton2 INSTANCE = new Singleton2();
}
private Singleton2 (){}
publicstaticfinal Singleton2 getInstance(){
return SingletonFactory.INSTANCE;
}
}
使用静态内部类的方式,既实现了线程安全,又避免了同步带来的性能影响。
饿汉模式
饿汉模式是指类初始化的时候就已经自行实例化了,天生就是线程安全的,不需要考虑线程安全的问题
publicclass Singleton3 {
private Singleton3(){}
privatestatic Singleton3 singleton3 = new Singleton3();
publicstatic Singleton3 getInstance(){
returnsingleton3;
}
}