什么是单例模式
单例模式,是一种常用且简单的软件设计模式,属于创建型模式。应用单例模式的类在全局范围内必须只能有一个实例对象存在,且外部不需要实例化对象,就可以访问这个类的唯一实例对象。
注意:
应用场景与注意事项
在以下情况下可以考虑使用单例模式:
优点:
缺点:
使用注意事项:
使用时不能用反射模式创建单例,否则会实例化一个新的对象 ;使用单例模式时注意线程安全问题
单例模式的几种实现场景
1、懒汉模式【线程不安全】
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这是比较简单的单例模式实现方式,采用延迟加载的方式,等到被使用时才实例化对象,资源利用率高。但是多线程下,会出现线程安全问题。
2、懒汉模式【线程安全】
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种方式与第一种方式的区别在于 geInstance() 方法增加了 synchronized 关键词修饰,保证了线程安全问题,但是这样会影响程序性能。
3、饿汉模式【天生线程安全】
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
这种方式在类装载的时候就完成实例化,避免了线程安全问题。但是如果程序从来没有使用这个实例就容易找到资源浪费。
4、双重检查锁模式【线程安全】(推荐)
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
在这种双重检查锁下,可以保证多线程安全同时保证程序性能。
5、静态内部类模式【线程安全】(推荐)
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
这种方式可以达到双重检查锁模式一样的性能,是线程安全的。它跟饿汉模式类似,两者都是采用了类装载的机制来保证初始化实例时只有一个线程。但是饿汉模式只要类被装载就会实例化,没有延迟加载的作用,而静态内部类方式在类被装载时并不会立即实例化,而是在需要使用实例的时候才会装载类,从而完成的实例化。
类的静态属性只会在第一次加载类的时候初始化,JVM保证了在类进行初始化时,别的线程是无法进入的,所以说是线程安全的。
6、枚举模式【线程安全】(推荐)
public enum Singleton {
INSTANCE;
public void doSomething() {
}
}
JDK1.5后增加了枚举类型,我们可以通过枚举的方式简单地创建单例模式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,防止对象被多次实例化。
在实际工作中,我经常使用的是静态内部类模式。以上就是今天《单例模式》的讲解,良好的代码风格需要长期不断的积累学习。