1. Singleton模式介绍:
Singleton模式也成为单件模式,即确保一个类只有一个实例,并提供一个全局的访问点.
类图:
Singleton
Static instance
//其他有用的单件数据
Static getInstance()
//其他有用的单件方法
2. Singleton模式的实现:
public class SingletonMethod {
private static SingletonMethod instance = null;
private SingletonMethod(){
}
public static SingletonMethod getInstance() {
if (null == instance) {
instance = new SingletonMethod2();
}
return instance;
}
/**
* @param args
*/
public static void main(String[] args) {
SingletonMethod test1= SingletonMethod.getInstance();
SingletonMethod test2= SingletonMethod.getInstance();;
System.out.println(test1.equals(test2));
System.out.println(test1.hashCode()==test2.hashCode());
}
}
实现的说明;构造器是私有的,保证不能被外部类所直接创建.在通过getInstance()来调用时,判断实例是否已经创建,如果没有创建再进行创建.通过测试我们验证了创建2次出的实例确实时一个.真的很简单.那我们还是来看看下面的注意事项吧!
3. Singleton模式的注意事项
上面的实现好像很好,不过上面的做法却不能保障我们每次取到的实例就是一个,那么是什么时候呢?让我们来看看.当我们程序中使用了多线程的时候,确实有创建了两个不同实例的时候,究竟是为什么呢?研究发现,其实有时候会有两个线程同时去访问getInstance(),发现instance为null,那么他们都会去创建这个实例并返回,这样就会产生两个实例了.哈哈,问题找到了,我们要怎么来修改呢?
首先我们想到的是,多线程并发时我们可以使用synchronized的,我们这样来修改一下:
public static synchronized SingletonMethod2 getInstance() {
if (null == instance) {
instance = new SingletonMethod2();
}
return instance;
}
问题得到解决了,可以仔细考虑时我们发现,还有一个比较严重的问题,只有第一次执行此方法才需要同步,那么我们每次都来同步它,一定会降低效率的.如果您能接收这样的处理负担,那么这样的方法还是很好的,简单有效.
那么有办法改善多线程嘛?参见以下处理方法:
1. 使用”急切”创建实例,二不用延迟实例化的做法
public class SingletonTest {
private SingletonTest() {
}
private static SingletonTest instance = new SingletonTest();
public static SingletonTest getInstance() {
return instance;
}
public static void main(String[] args) {
SingletonTest test1= SingletonTest.getInstance();
SingletonTest test2= SingletonTest.getInstance();;
System.out.println(test1.equals(test2));
System.out.println(test1.hashCode()==test2.hashCode());
}
}
2. 使用”双重加锁”的办法
private volatile static SingletonMethod2 instance = null;
public static SingletonMethod2 getInstance() {
if (null == instance) {
synchronized (SingletonMethod2.class) {
if (null == instance) {
instance = new SingletonMethod2();
}
}
}
return instance;
}
Volatile 关键字确保,当instance变量被初始化为singleton实例时,多个线程能正确地处理instance变量.
注:双重加锁不适用于1.4及更早的JDK.
总结一些吧:其实大多数人都了解singleton模式,在使用的过程中也都用过,不过你们注意了这些可能的问题了嘛?
Singleton模式也成为单件模式,即确保一个类只有一个实例,并提供一个全局的访问点.
类图:
Singleton
Static instance
//其他有用的单件数据
Static getInstance()
//其他有用的单件方法
2. Singleton模式的实现:
public class SingletonMethod {
private static SingletonMethod instance = null;
private SingletonMethod(){
}
public static SingletonMethod getInstance() {
if (null == instance) {
instance = new SingletonMethod2();
}
return instance;
}
/**
* @param args
*/
public static void main(String[] args) {
SingletonMethod test1= SingletonMethod.getInstance();
SingletonMethod test2= SingletonMethod.getInstance();;
System.out.println(test1.equals(test2));
System.out.println(test1.hashCode()==test2.hashCode());
}
}
实现的说明;构造器是私有的,保证不能被外部类所直接创建.在通过getInstance()来调用时,判断实例是否已经创建,如果没有创建再进行创建.通过测试我们验证了创建2次出的实例确实时一个.真的很简单.那我们还是来看看下面的注意事项吧!
3. Singleton模式的注意事项
上面的实现好像很好,不过上面的做法却不能保障我们每次取到的实例就是一个,那么是什么时候呢?让我们来看看.当我们程序中使用了多线程的时候,确实有创建了两个不同实例的时候,究竟是为什么呢?研究发现,其实有时候会有两个线程同时去访问getInstance(),发现instance为null,那么他们都会去创建这个实例并返回,这样就会产生两个实例了.哈哈,问题找到了,我们要怎么来修改呢?
首先我们想到的是,多线程并发时我们可以使用synchronized的,我们这样来修改一下:
public static synchronized SingletonMethod2 getInstance() {
if (null == instance) {
instance = new SingletonMethod2();
}
return instance;
}
问题得到解决了,可以仔细考虑时我们发现,还有一个比较严重的问题,只有第一次执行此方法才需要同步,那么我们每次都来同步它,一定会降低效率的.如果您能接收这样的处理负担,那么这样的方法还是很好的,简单有效.
那么有办法改善多线程嘛?参见以下处理方法:
1. 使用”急切”创建实例,二不用延迟实例化的做法
public class SingletonTest {
private SingletonTest() {
}
private static SingletonTest instance = new SingletonTest();
public static SingletonTest getInstance() {
return instance;
}
public static void main(String[] args) {
SingletonTest test1= SingletonTest.getInstance();
SingletonTest test2= SingletonTest.getInstance();;
System.out.println(test1.equals(test2));
System.out.println(test1.hashCode()==test2.hashCode());
}
}
2. 使用”双重加锁”的办法
private volatile static SingletonMethod2 instance = null;
public static SingletonMethod2 getInstance() {
if (null == instance) {
synchronized (SingletonMethod2.class) {
if (null == instance) {
instance = new SingletonMethod2();
}
}
}
return instance;
}
Volatile 关键字确保,当instance变量被初始化为singleton实例时,多个线程能正确地处理instance变量.
注:双重加锁不适用于1.4及更早的JDK.
总结一些吧:其实大多数人都了解singleton模式,在使用的过程中也都用过,不过你们注意了这些可能的问题了嘛?