一.单例模式介绍
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式要点:
- 单例类只能有一个实例------------>类构造器私有化
- 单例类必须自己创建自己的实例------------>类内部创建实例对象
- 单例类必须给所有其他对象提供这一实例------------>一个公共的方法能返回该单例类的唯一实例
二.代码:
1.懒汉式:
//线程不安全
class Singleton {
private static Singleton singleton = null;//唯一实例
private Singleton(){}//构造方法
public static Singleton getInstance() {//get方法
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉模式:只有到使用时才初始化类的实例对象。
2.懒汉式(线程安全版):
//线程安全
class Singleton {
private static Singleton singleton = null;//唯一实例
private Singleton(){}//构造方法
public static synchronized Singleton getInstance() {//get方法
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
通过synchronized修饰get方法,保证多线程的线程安全。
3.饿汉式(静态常量):
class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){}//构造方法
public static Singleton getInstance() {//get方法
return singleton;
}
}
饿汉模式:类加载的时候就初始化对象实例。这样可保证多线程下的线程安全。
4.饿汉式(静态代码块):
class Singleton {
private static Singleton singleton;
private Singleton(){}//构造方法
static {
singleton = new Singleton();
}
public static Singleton getInstance() {//get方法
return singleton;
}
}
静态代码块在类加载时会提前执行,所以也能保证在使用时该实例是唯一的。并且线程安全。
5.双重校验锁:
class Singleton {
private static volatile Singleton singleton;
private Singleton(){}//构造方法
public static Singleton getInstance() {//get方法
if (singleton == null) {//第一次校验
synchronized (Singleton.class){
if(singleton==null){//第二次校验
singleton = new Singleton();
}
}
}
return singleton;
}
}
双重校验可以减少锁获取和等待的时间,synchronized关键字保证线程安全。
注意:禁止指令重排优化这条语义直到jdk1.5以后才能正确工作。此前的JDK中即使将变量声明为volatile也无法完全避免重排序所导致的问题。所以,在jdk1.5版本前,双重检查锁形式的单例模式是无法保证线程安全的。
6.静态内部类:
class Singleton {
private static class Holder {
private static Singleton singleton = new Singleton();
}
private Singleton(){}
public static Singleton getSingleton(){
return Holder.singleton;
}
}
静态内部类的加载不需要依附外部类,在使用时才加载,不过在加载静态内部类的过程中也会加载外部类,这样就实现了需要延时加载的需求。