在一个应用程序里面,某个类的实例对象只有一个,你没办法去new,因为构造器是被 private
修饰的,易班通过其get方法获取到他们的实例。
懒汉式单例
// 线程不安全
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
// 线程安全
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉式单例—双重检验
public class Singleton {
// volatile 避免指令重排序问题
private volatile static Singleton singleton;
private Singleton () {
}
public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
// 保证singleon在多线程中的可见性,可以立即刷新到主内存
// new Singleton() (1-开辟空间,2-初始化空间,3-赋值实例对象)
// 操作会发生指令重排
// new创建了实例并赋值给了singleton,但是构造方法初始化空间步骤并未执行
singleton = new Singleton();
}
}
}
return singleton;
}
}
饿汉式单例
// 静态常量方式
public class Singleton {
private final static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
// 静态代码块方式
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
静态内部类
public class Singleton {
private static class SingletonHolader {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
实际应用场景
1、在Spring中创建的Bean实例默认都是单例模式存在的。
2、网站的计数器,一般也是单例模式实现,否则难以同步。
3、应用程序的日志应用,一般都用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。