对于单例模式,有很多种不同的用法,每种用法也有各自的特点
饿汉式单例模式
该模式用static修饰了创建对象s,其优点就是保证了使用过程中线程的安全性
但是缺点就是占用了资源
/**
* 单例实现-饿汉式
* 特点:线程安全,无法实现实例懒加载策略。
*/
private static final Single s=new Single();
public Single(){}
public static Single getInstance(){
return s;
}
懒汉式单例模式
相对于饿汉模式的内存占用,可以改进按需加载模式,也就是懒汉模式。
优点:懒汉式的好处是显而易见的,它尽最大可能节省了内存空间。
缺点:在多线程编程中,使用懒汉式可能会造成类的对象在内存中不唯一。
导致这一现象的原因是在高并发环境下,有可能多个线程同时访问,但是此时若s2为空,那就会创建多个s2对象。
虽然通过修改代码可以改正这些问题,但是效率却又降低了。
/**
* 单例模式-懒汉式
*
* 懒汉式和饿汉式相比的区别就是懒汉式创建了延迟对象同时饿汉式的实例对象是被修饰为final类型。
* 特点:线程不安全,实现了实例懒加载策略。
*/
private static Single s2;
private Single(){}
public static Single getInstance2(){
if (s2==null)//多个并行的线程同时访问导致创建多个s对象,不安全。
return s2=new Single();
return s2;
}
全局加锁式单例模式
既然懒汉模式会导致对象不唯一,那么对它相应的改进加锁也可以解决这个问题。
对它的静态方法synchronized加锁来解决高并发环境下出现的问题,当然很明显的降低了程序运行的效率。
/**
* 单例模式-全局锁式
*
* 特点:线程安全,且实现了懒加载策略,但是线程同步时效率不高。
*/
private static Single s3;
private Single(){}
public synchronized static Single getInstance3(){
if (s3==null)
return s3=new Single();
return s3;
}
双重校验式单例模式
这种模式也就是对全局锁的一种优化,优化了锁粒度,提升了线程运行的效率
/**
* 单例模式-双重校验锁式
* 特点:线程安全,且实现了懒加载策略,同时保证了线程同步时的效率。
* volatile强制当前线程每次读操作进行时,保证所有其他的线程的写操作已完成。
* volatile使得JVM内部的编译器舍弃了编译时优化,对于性能有一定的影响。
*/
private static volatile Single s4;
private Single(){}
public static Single getInstance4(){
if (s4==null){
synchronized (Single.class){
if (s4==null) return s4=new Single();
}
}
return s4;
}
静态代码块式单例模式
/**
* 静态代码块式
* 特点:线程安全,类主动加载时才初始化实例,实现了懒加载策略,且线程安全。
*/
private final static Single s5;
private Single() { }
static {
s5 = new Single();
}
public static Single getInstance() {
return s5;
}
静态内部类式单例模式
单例对象在程序第一次 getInstance() 时主动加载 SingletonHolder 和其静态成员 s6,
因而实现了懒加载策略。
/**
* 单例模式-静态内部类式【推荐】
* 特点:线程安全,不存在线程同步问题,
*/
private Single() {}
private static class SingletonHolder {
private static final Single s6 = new Single();
}
public static Single getInstance6() {
return SingletonHolder.s6;
}
枚举型单例模式
单例对象在枚举类型 INSTANCE第一次引用时通过枚举的构造函数初始化,因而实现了懒加载策略。 该方式不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。 但是,枚举是在JDK 1.5中才新加入。
/**
* 单例模式-枚举方式
*
* 特点:线程安全,不存在线程同步问题
*/
private Single() {}
enum SingletonEnum {
INSTANCE;
private final Single s7;
private SingletonEnum() {
s7 = new Single();
}
}
public static Single getInstance() {
return SingletonEnum.INSTANCE.s7;
}
以上就是对其中对于单例模式的总结了,可以看到很多方法也都是一步一步慢慢优化的,以提升运行时效率问题及安全问题。