1 懒汉式 写法一
这种写法是最普通的写法,在单线程中,构造被私有,只有sMSingletonDemo1为null的时候才会创建一个实例,但是在多线程中,当两个线程同时运行到sMSingletonDemo1==null的判断时,而sMSingletonDemo1确实没创建出来,这时候就有可能创建出两个实例,因此是为线程不安全。
public class SingletonDemo1 {
private static SingletonDemo1 sMSingletonDemo1=null;
private SingletonDemo1(){
}
public static SingletonDemo1 getInstance(){
if (sMSingletonDemo1==null){
sMSingletonDemo1=new SingletonDemo1();
}
return sMSingletonDemo1;
}
}
2 懒汉式 写法二
针对写法一的多线程使用时可能创建出多个实例来,是线程不完全的范畴,可以采用解决线程安全的方法来解决
关键字synchronized的作用是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次,只能有一个线程进入同步块,从而保证线程间的安全性。
当有两个以上的线程同时运行到sMSingletonDemo1==null的判断时,第一个线程加上锁后,第二个线程只能等待,当第一个线程释放锁后,第二个线种才能加上锁,这时sMSingletonDemo1已创建,自然不会再次创建实例了
这种写法相对来说,每次调用的时候都经历了加锁与释放锁的过程,因此比较耗时。
public class SingletonDemo2 {
private static SingletonDemo2 sMSingletonDemo2=null;
private SingletonDemo2(){
}
public static synchronized SingletonDemo2 getInstance(){
if (sMSingletonDemo2==null) {
sMSingletonDemo2=new SingletonDemo2();
}
return sMSingletonDemo2;
}
}
3 懒汉式 写法三
针对写法二的优化
public class SingletonDemo3 {
private static SingletonDemo3 sMSingletonDemo2=null;
private SingletonDemo3(){
}
public static SingletonDemo3 getInstance(){
if (sMSingletonDemo2==null) {
synchronized (SingletonDemo3.class) {
sMSingletonDemo2 = new SingletonDemo3();
}
}
return sMSingletonDemo2;
}
}
写法二 每次调用的时候都经历了加锁与释放锁的过程,因此比较耗时,在这时我们把同步锁块加入到内部,只有当sMSingletonDemo2实例为null时才会走加锁创建实例的过程。
4 饿汉式
当类加载的时候,就会创建类的实例,有点浪费内存空间,没有懒汉式的延迟加载特点。
public class SingletonDemo4 {
private static SingletonDemo4 sMSingletonDemo2=new SingletonDemo4();
private SingletonDemo4(){
}
public static SingletonDemo4 getInstance(){
return sMSingletonDemo2;
}
}
5 静态内部类的综合使用
结合了饿汉式与懒汉式的优点
public class SingletonDemo5 {
private SingletonDemo5(){
}
private static class SingletonHolder{
private final static SingletonDemo5 mSingletonDemo5=new SingletonDemo5();
}
public static SingletonDemo5 getInstance(){
return SingletonHolder.mSingletonDemo5;
}
}