单例模式
- 懒汉模式
public class Singleton_01 {
//懒汉模式(线程不安全)
public static Singleton_01 instance;
private Singleton_01() {
}
public static Singleton_01 getInstance(){
if(instance!=null){
return instance;
}
instance=new Singleton_01();
return instance;
}
//
}
- 单例模式有⼀个特点就是不允许外部直接创建,也就是new Singleton_01(),因此这⾥在默认的构造函数上添加了私有属性 private。
- ⽬前此种⽅式的单例确实满⾜了懒加载,但是如果有多个访问者同时去获取对象实例你可以想象成⼀堆⼈在抢厕所,就会造成多个同样的实例并存,从⽽没有达到单例的要求。
- 线程安全的懒汉模式
直接用锁实现
public class Singleton_01 {
//懒汉模式(线程不安全)
public static Singleton_01 instance;
private Singleton_01() {
}
public static synchronized Singleton_01 getInstance(){
if(instance!=null){
return instance;
}
instance=new Singleton_01();
return instance;
}
//
}
- 此种模式虽然是安全的,但由于把锁加到⽅法上后,所有的访问都因需要锁占⽤导致资源的浪费。如果不是特殊情况下,不建议此种⽅式实现单例模式。
- 饿汉模式
线程安全
public class Singleton_02 {
//恶汉模式(线程安全)
public static Singleton_02 instance=new Singleton_02();
private Singleton_02() {
}
public static Singleton_02 getInstance(){
return instance;
}
}
- 但此种⽅式并不是懒加载,也就是说⽆论你程序中是否⽤到这样的类都会在程序启动之初进⾏创建。
- 那么这种⽅式导致的问题就像你下载个游戏软件,可能你游戏地图还没有打开呢,但是程序已经将这些地图全部实例化。到你⼿机上最明显体验就⼀开游戏内存满了,⼿机卡了,需要换了。
- 使用类的内部类(线程安全)
静态类部类
public class Singleton_03 {
// 静态内部类
public static class SingletonHolder{
private static Singleton_03 instance=new Singleton_03();
}
private Singleton_03(){
}
public static Singleton_03 getInstance(){
return SingletonHolder.instance;
}
}
- 使⽤类的静态内部类实现的单例模式,既保证了线程安全有保证了懒加载,同时不会因为加锁的⽅式耗费性能。
- 这主要是因为JVM虚拟机可以保证多线程并发访问的正确性,也就是⼀个类的构造⽅法在多线程环境下可以被正确的加载。
- 此种⽅式也是⾮常推荐使⽤的⼀种单例模式
- 双重锁校验(线程安全)
public class Singleton_04 {
private static Singleton_04 instance;
private Singleton_04() {
}
public static Singleton_04 getInstance(){
if(instance!=null){
return instance;
}
synchronized (Singleton_04.class){
if(instance==null){
instance = new Singleton_04();
}
}
return instance;
}
}
- 双锁的⽅式是⽅法级锁的优化,减少了部分获取实例的耗时。同时这种⽅式也满⾜了懒加载。
- 同时这种⽅式也满⾜了懒加载。
- 枚举方式(推荐)
public class SingletonObject7 {
private SingletonObject7(){
}
/**
* 枚举类型是线程安全的,并且只会装载一次
*/
private enum Singleton{
INSTANCE;
private final SingletonObject7 instance;
Singleton(){
instance = new SingletonObject7();
}
private SingletonObject7 getInstance(){
return instance;
}
}
public static SingletonObject7 getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
- 这种⽅式解决了最主要的;线程安全、⾃由串⾏化、单⼀实例。
参考资料:
- 重学java设计模式