定义 :
保证全局绝对只有一个实例对象
单例类必须自己创建自己的唯一实例
单例必须给所有其他对象提供这一实例
单例的实现方式
类加载时就实例化对象
/*
饿汉单例模式
特征 类加载时就实例化对象
优点 线程安全 还没线程时就实例化了 所以线程绝对安全的
缺点 可能会带来内存浪费占茅坑不拉屎的想象 适用于实例数量少的场景
*/
public class HungrySingleton {
// 类加载顺序 先静态后动态 先属性后方法 先上后下
// 类加载时就会被实例化
private static HungrySingleton instance = new HungrySingleton();
// 构造函数必须私有 这样才不会被外部对象实例化
private HungrySingleton(){}
// 获取唯一可用的对象 (获取实例有则返回无则创建) static让全局可访问
public static HungrySingleton getInstance() {
return instance;
}
}
被外部类调用时才初始化实例
/**
* 懒汉模式
* 特征 被外部类调用时才初始化实例
* 优点 不浪费内存 不提前初始化 用时再初始化
* 缺点 多线程下不安全
*
*/
public class LazySingleton {
private static LazySingleton instance = null;
LazySingleton(){ }
public static LazySingleton getInstance() {
if(null==instance){
instance = new LazySingleton();
}
return instance;
}
}
package com.liao.edu.lazy;
/**
* 懒汉模式+双重检查加锁
* 特征 被外部类调用时才初始化实例
* 优点 调用方法有条件触发锁 锁的粒度更细 线程安全的
* 缺点 还是会触发锁,会被反序列化破坏
*/
public class LazyDoubleCheckSingleton {
//volatile 防止指令重拍
//因为 instance = new DoubleCheckLazySingleton(); 实例化过程并不是原子性的
//所以加volatile防止指令重排(123顺序可能错乱 导致其他线程调用时instance!=null )
private volatile static LazyDoubleCheckSingleton instance = null;
//私有化保证不被外部初始化
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance() {
//有条件加锁避免调用就上锁 即减少同步锁的竞争
if(null==instance){
synchronized (LazyDoubleCheckSingleton.class){
//保证单例
if(null==instance){
instance = new LazyDoubleCheckSingleton();//不是原子操作
//1.创建内存空间
//2.在内存空间内创建对象
//3.将内存空间复制给变量instance
}
}
}
return instance;
}
}
package com.liao.edu.register;
/**
* 枚举单例
* 枚举天生不能被反射破坏 Cannot reflectively create enum objects
* 枚举天生线程安全 private volatile transient Map<String, T> enumConstantDirectory = null;
* 优点 写法优雅简单 防止反射 线程安全
* 缺点 底层是饿汉式的实现 内存浪费 不能大量使用
*/
public enum EnumSingleton {
INSTANCE;
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public static EnumSingleton getInstance() {
return INSTANCE;
}
}
package com.liao.edu.register;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 容器注册单例
* 适用于单例非常多的情况,便于管理
*/
public class ContainerSingleton {
private static Map<String,Object> map = new ConcurrentHashMap<String,Object>();
//无参私有的构造函数
private ContainerSingleton(){}
public static Object getInstance(String className) {
if(!map.containsKey(className)){
synchronized (ContainerSingleton.class){
if(!map.containsKey(className)){
try{
map.put(className,Class.forName(className).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return map.get(className);
}
}