一:恶汉模式,类加载的时候就已经把对象初始化好了。(为了防止在其他类中使用new 操作符创建对象,要使用一个private 标记的 构造方法)
package single;
public class Singleton1 {
public static final Singleton1 singleton=new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance(){
return singleton;
}
}
package single;
public class Singleton2 {
public static Singleton2 singleton2 = null;
private Singleton2() {
// TODO Auto-generated constructor stub
}
public static Singleton2 getInstance() {
if (singleton2 == null) {// 1
singleton2 = new Singleton2();//2
}
return singleton2;
}
}
先执行第二步生成的那个对象。怎么办呢,加锁啊。。
三:加上同步锁
package single;
public class Singleton3 {
public static Singleton3 singleton3 = null;
private Singleton3() {
// TODO Auto-generated constructor stub
}
public synchronized static Singleton3 getInstance() {
if (singleton3 == null) {// 1
singleton3 = new Singleton3();// 2
}
return singleton3;
}
}
四:同步锁2
package single;
public class Singleton4 {
public static Singleton4 singleton4=null;
private Singleton4() {
// TODO Auto-generated constructor stub
}
public static Singleton4 getInstance(){
if(singleton4==null){//1
synchronized(Singleton4.class){
singleton4 =new Singleton4();//2
}
}
return singleton4;
}
}
五:同步锁3
package single;
public class Singleton5 {
public static Singleton5 singleton5=null;
private Singleton5() {
// TODO Auto-generated constructor stub
}
public static Singleton5 getInstance(){
if(singleton5==null){//1
synchronized(Singleton5.class){
if(singleton5==null){//2
singleton5 =new Singleton5();//3
}
}
}
return singleton5;
}
}
五:变量singleton5前加volatile 关键字(volatile关键字保证了可见性,但不保证原子性,可见性的意思就是,一个线程对一个资源的修改,另一个线程会得到通知。可以参考这篇blog)不过据说有些jvm并没有实现volatile规范。。。。。)
六:内部类方式。
如果想保证线程安全,不想要lazy加载的话,第一种最合适,但如果想要线程安全,又先要lazy加载的话,我们还可以使用内部类的方式。
package single;
public class Singleton6 {
private static class InnerClass {
public static final Singleton6 singleton6 = new Singleton6();
}
public static Singleton6 getInstance() {
return InnerClass.singleton6;
}
}
七:最高端大气上档次的是enum枚举类的方式
package single;
public enum Singleton7 {
singleton7;
}