常见单例模式:饿汉式 懒汉式
饿汉式
public class Singleton1 {
private Singleton1(){};
private static final Singleton1 s = new Singleton1();
public static synchronized Singleton1 getS(){
return s;
}
}
这种方式在类加载时就创建了一个实例对象, 避免了多线程的同步问题,获取对象的速度快, 但是启动过程比较消耗资源
另:构造函数 成员变量修饰符采用的都是private 即:在当前类中有效,为了避免在其他类中有new Singleton()的行为.
懒汉式
public class Singleton {
private static Singleton s;
private Singleton(){};
public static Singleton gets(){
if(s==null){
s=new Singleton();
}
return s;
}
}
懒汉模式申明了一个静态对象,在用户第一次调用时进行实例化创建,后续调用返回第一次创建的对象,但是它的线程是不安全的,多线程并发请求下可能出现创建多个对象的情况.
为了保证线程安全 通常情况下是加锁
public class Singleton {
private static Singleton s;
private Singleton(){};
public static synchronized Singleton gets(){
if(s==null){
s=new Singleton();
}
return s;
}
}
这种情况下 虽然保证了线程的安全,但是除第一次创建对象外,其他线程为判断对象是否为空就需要频换获取释放锁对象,锁的开销很大
锁下移,并保证第一次并发请求创建时的 安全问题
public class Singleton {
private static Singleton s;
private static String abc;
private Singleton(){};
public static Singleton gets(){
if(s==null){
//线程A 线程B 同时执行到这一步
synchronized(abc){
//A执行完,B进行创建前,再次判断对象是否创建,避免创建两个对象
if(s==null){
s=new Singleton();
}
}
}
return s;
}
}