- 定义
无论在什么情况下,定义为单例的类只有一个实例。
- 实现思想
单例模式的实现思想是,通过把构造器私有化,提供一个唯一的访问点返回该类的对象,达到不重复构造该类的目的。 - 应用场景
配置文件的加载,使用线程池获取一个线程等。 - 几种实现方式
懒汉式实现
第一种
/**
* 不使用synchronized关键字,存在线程安全问题
* 使用之后,性能低
*/
public class LazySimpleSingletion {
private static LazySimpleSingletion instance;
private LazySimpleSingletion(){}
public synchronized static LazySimpleSingletion getInstance(){
if(instance == null){
instance = new LazySimpleSingletion();
}
return instance;
}
}
第二种
/**
* 把synchronized放到方法内部,必须使用双重检,如果内部不检查,会创
* 建多个实例
* 如果不使用volatile关键字,存在指令重排序的问题
*/
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton instance;
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
//检查是否要阻塞
if (instance == null) {
synchronized (LazyDoubleCheckSingleton.class) {
//检查是否要重新创建实例
if (instance == null) {
instance = new LazyDoubleCheckSingleton();
//指令重排序的问题
}
}
}
return instance;
}
}
第三种
/**
* 使用内部类的方式实现,写法优雅,但是会被反射破坏
* 如果不想被反射破坏,需要在构造器中做判断,这样使代码可读性变差
*/
public class LazyStaticInnerClassSingleton {
private LazyStaticInnerClassSingleton(){
// if(LazyHolder.INSTANCE != null){
// throw new RuntimeException("不允许非法访问");
// }
}
static LazyStaticInnerClassSingleton getInstance(){
return LazyHolder.INSTANCE;
}
private static class LazyHolder{
private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
}
}
饿汉式实现
/**
* 优点:执行效率高,性能高,没有任何的锁
* 缺点:某些情况下,可能会造成内存浪费
*/
public class HungrySingleton {
private static final HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
public class HungryStaticSingleton {
//先静态后动态
//先上,后下
//先属性后方法
private static final HungryStaticSingleton hungrySingleton;
//装B 写法,和上面的实现方式没有区别
static {
hungrySingleton = new HungryStaticSingleton();
}
private HungryStaticSingleton(){}
public static HungryStaticSingleton getInstance(){
return hungrySingleton;
}
}
注册式
使用容器的思想,初次实例化把实例对象放到容器中,以后再取从容器中获取。
public class ContainerSingleton {
private ContainerSingleton(){}
private static Map<String,Object> ioc = new ConcurrentHashMap<String, Object>();
public static Object getInstance(String className){
Object instance = null;
if(!ioc.containsKey(className)){
try {
instance = Class.forName(className).newInstance();
ioc.put(className, instance);
}catch (Exception e){
e.printStackTrace();
}
return instance;
}else{
return ioc.get(className);
}
}
}
ThreadLocal
使用这种方式保证单线程中是单例的,不同线程之间是多例的。
public class ThreadLocalSingleton {
private static final ThreadLocal<ThreadLocalSingleton> threadLocaLInstance =
new ThreadLocal<ThreadLocalSingleton>(){
@Override
protected ThreadLocalSingleton initialValue() {
return new ThreadLocalSingleton();
}
};
private ThreadLocalSingleton(){}
public static ThreadLocalSingleton getInstance(){
return threadLocaLInstance.get();
}
}