保证某一个类有且只有一个实例,它提供全局访问的方法,这个类称为单例类。单例模式是一种对象创建型模式。
1. 提供对唯一实例的受控访问。
2. 内存中只存在一个实例,减少系统开销,对需要频繁创建和销毁的对象单例模式可以提高系统的性能。
3. 允许可变数目的实例。
常用的单例模式:
1. 饿汉式: 线程安全(类加载机制保证),调用效率高(没有访问同步问题),但是,不能延时加载(加载类的时候直接初始化了实例)
public class Singleton {
//2. 内部自行实例化
//类加载后 直接初始化,没有延时加载的优势
//类加载的时候,天然就是线程安全的,不需要同步块,效率高
private static Singleton instance = new Singleton();
//1私有化构造器
private Singleton() {
//对象只有一个,简单说就是构造器只会被调用一次,当再次调用会直接抛出异常,防止反射
if(instance != null){
throw new RuntimeException("error");
}
}
//3.提供全局访问点
public static Singleton getInstance(){
return instance;
}
//反序列化时直接调用返回实例
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
2. 懒汉式: 线程安全,调用效率不高,但是,可以延时加载
public class Singleton {
//和饿汉式不同的是类加载的时候没有初始化,而是在第一次使用时初始化
private static Singleton instance;
private Singleton() {
//对象只有一个,简单说就是构造器只会被调用一次,当再次调用会直接抛出异常,防止反射
if(instance != null){
throw new RuntimeException("error");
}
}
//反序列化时直接调用返回实例
private Object readResolve() throws ObjectStreamException {
return instance;
}
/**
* 多个线程同时访问,可能会造成加载多个对象,需要同步块,线程安全,但是调用效率就不高了
*
* @return
*/
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
3. 静态内部类式:线程安全,调用效率高,可以延迟加载
public class Singleton {
/**
* 加载外部类的时候,不会立即加载内部类,
* @author MrJia
*
*/
private static class SingletonClassInstance{
//保证只有一个 static final
private static final Singleton instance = new Singleton();
}
// 提供全局访问点,当第一次访问时会去加载内部类,起到延时加载的作用
public static Singleton getInstance(){
return SingletonClassInstance.instance;
}
//私有构造器
private Singleton() {
}
}
4. 枚举单例:线程安全、调用效率高,不能延时加载
public enum Singleton {
//枚举元素本身就是单例
INSTANCE;
}
注意:内部类方式和枚举方式 本身就没有反射和反序列化的问题
单例还有双重锁的实现方式,但因为编译器优化和JVM底层模型的问题,使用时偶尔会出错,就不介绍了。