单例模式
Posted wq-9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
单例模式官方定义
确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。
单例模式的实现机制
实现单例模式的思路是,为了防止客户程序利用构造方法创建多个对象,将构造方法声明为private类型。其原因是,如果构造方法为public类型,则客户程序永远可以通过使用改构造方法创建不同的对象。但这样做的问题是,如果一个类的构造方法是private的,则其他类无法使用该构造方法来创建对象,从而该类就成为不可用的了。为了解决此问题,该类必须提供一个实例方法,通常声明为getinstance方法。该方法返回一个实例。该方法为静态的,否则客户程序无法调用。
Volatile变量
在程序设计中,尤其是在C语言、C++、C#和Java语言中,使用volatile关键字声明的变量或对象通常具有与优化、多线程相关的特殊属性。通常,volatile关键字用来阻止(伪)编译器认为的无法“被代码本身”改变的代码(变量/对象)进行优化。如在C语言中,volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
在C环境中,volatile关键字的真实定义和适用范围经常被误解。虽然C++、C#和Java都保留了C中的volatile关键字,但在这些编程语言中volatile的用法和语义却大相径庭。
在C,以及C++中,volatile关键字的作用[1]:
- 允许访问内存映射设备
- 允许在
setjmp
和longjmp
之间使用变量 - 允许在信号处理函数中使用sig_atomic_t变量
根据相关的标准(C,C++,POSIX,WIN32)和目前绝大多数实现,对volatile变量的操作并不是原子的,也不能用来为线程建立严格的happens-before关系。volatile
关键字就像便携式线程构建一样基本没什么用处[2][3][4][5][6]。
Visual C++ 2005 保证volatile变量是一种内存屏障,阻止编译器和CPU重新安排读入和写出语义。[7] 在先前版本的Visual C++则没有此类保证。在其他方面将指针定义为volatile可能会影响程序的性能。例如,如果指针定义对代码的其他地方可见,强制编译器将指针视为屏障,就会降低程序的性能,这是完全不必要的。
对用户定义的非基本数据类型使用volatile
基本类型的对象用volatile修饰后,仍旧支持所有的操作(加、乘、赋值等)。但是,用户定义的非基本类型(class、struct、union)的对象被volatile修饰后,具有不同行为:
- 只能调用volatile成员函数;即只能访问它的接口的子集。
- 只能通过const_cast运算符转为没有volatile修饰的普通对象。即由此可以获得对类型接口的完全访问。
- volatile性质会传递给它的数据成员。
代码如下
public class Singleton {
private static volatile Singleton instance=null;
private Singleton(){
}
//静态工厂方法
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
package com.wanson.designpatten;
import java.util.Calendar;
public class Driver {
public static void main(String[] args) {
Singleton instance=Singleton.getInstance();
System.out.println(instance);
Singleton secondInstance=Singleton.getInstance();
System.out.println(secondInstance);
Calendar calendar1= Calendar.getInstance();
System.out.println(calendar1);
Calendar calendar2=Calendar.getInstance();
System.out.println(calendar2);
}
}
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章