设计原则
- 开闭原则
- 依赖倒置原则
- 单一职责原则
- 接口隔离原则
- 迪米特法则
- 里氏替换原则
- 合成复用原则
饿汉式单例
/**
* 饿汉式单例(初始化就会创建)
* 优点:执行效率高,没有锁
* 缺点:某些情况会造成内存浪费
*/
public class HungrySingleton {
private static final HungrySingleton hungrySingleton = new HungrySingleton();
public HungrySingleton() {
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
懒汉式
/**懒汉式单例
* 使用的时候才会创建
* 优点:节省内存
* 缺点:线程不安全
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
public LazySingleton() {
}
public static LazySingleton getInstance(){
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
双重检查锁
/**
* 双层锁懒汉(解决线程不安全问题)
* 优点:性能高了,线程安全
* 缺点:不优雅,代码可读性低,不利于初学者观看
*/
public class TwoLazySingleton {
private volatile static TwoLazySingleton singleton;
public TwoLazySingleton() {
}
public static TwoLazySingleton getInstance(){
//检查是否阻塞
if(singleton == null){
synchronized (TwoLazySingleton.class) {
//检查是否重新创建实例
if (singleton == null) {
singleton = new TwoLazySingleton();
//volatile 解决指令重排序的问题
}
}
}
return singleton;
}
}
静态内部类单例
/**
* 静态内部类单例
* 优点:代码优雅简单
* 缺点:可以被反射破坏
*/
public class LazyStaticSingleton {
public LazyStaticSingleton() {
}
private static LazyStaticSingleton getInstance(){
return LazyHolder.SINGLETON;
}
static class LazyHolder{
private static final LazyStaticSingleton SINGLETON = new LazyStaticSingleton();
}
}
静态内部类为什么是线程安全的
静态内部类的特点:外部类加载时不需要加载静态内部类,不被加载则不占用内存,(延迟加载)当外部类调用getInstance方法时,才加载静态内部类,静态属性保证了全局唯一,静态变量初始化保证了线程安全,所以这里的方法没有加synchronized关键字(JVM保证了一个类的 初始化在多线程下被同步加锁)