单例设计模式有两种形式:饱汉式和饿汉式
对于饱汉式来说,不会出现线程安全问题,实现代码如下:
package SingleStrategy;
public class SingleTest {
private final static SingleTest instance = new SingleTest();
private SingleTest(){
}
public static SingleTest newInstance(){
return instance;
}
}
对于饿汉式来说,如果下面这种写法会出现线程安全问题,应该注意
package my_java;
public class SingleTest{
private static SingleTest instance = null;
private SingleTest(){
}
public static SingleTest getInstance(){
if(instance == null){
instance = new SingleTest();
}
return instance;
}
}
上面这种写法,在单线程环境中不糊出错,但在多线程环境中会出现线程安全问题。
下面这段代码,是经过改进的,多线程环境下添加synchronized关键字
加同步锁后,两次判断实例是否存在。
package SingleStrategy;
public class SingleTest2 {
private static SingleTest2 instance = null;
private SingleTest2(){
}
public static SingleTest2 newInstance(){
if(null == instance){
synchronized(SingleTest2.class){
if(null == instance){
instance = new SingleTest2();
}
}
}
return instance;
}
}
只有当Instance为Null即没有创建时,需要加锁操作。当Instance已经创建出来后,则无须加锁。因此只在第一次的时候Instance为Null,因此只在第一次试图创建实例的时候需要加锁。这样效率提高。
SingleTon用加锁机制来保证在多线程环境下只创建一个实例,并且用两个if判断来提高效率。这样的代码实现起来比较复杂。容易出错,我们还是推荐使用饱汉式的单例设计模式。