设计模式、方法等
一.单例模式
1.定义:一个类只能有一个实例,并提供该实例的全局访问点。好处是有些实例在全局中只需要一个,使用单例模式可以避免一个全局使用的类(在自己项目当中就是user类)
2.设计要素
(1)一个私有构造函数
(2)一个私有静态变量
(3)一个公有静态函数
二.懒汉式(线程不安全)
1.先不创建实例,第一次被调用时创建
2.也没有synchronized,所以线程不安全,同时多线程条件下可能会实例化多个实例
3.有点是延迟了实例化,如果不使用该类,就不会被实例化
三.饿汉式(线程安全)
1.不管是否需要,直接实例化好(就像饿死鬼一样),然后需要的时候就直接调用方法
2.因为提前实例化好了,所以不需要考虑线程安全的问题
3.但也因为实例化好了,如果使用,就造成了资源的浪费
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {
}
public static Singleton getUniqueInstance() {
return uniqueInstance;
}
}
四.双重检查锁实现(线程安全) 突然发现就很顾名思义
1.首先需要检查两次
2.其次用synchronized保证了线程安全
3.相当于改进了的线程安全的懒汉模式,将锁的位置变了并多了一个检查,第一个判断是判断实例是否存在,锁之后的判断是只允许一个线程实例化,这样就只会在第一次的时候有线程阻塞的情况。
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
五.为什么要用volatile修饰uniqueInstance
因为新建一个对象分为3步:分配内存空间,初始化对象,将对象指向分配的内存地址;
但是jvm有指令重排的特性,单线程的时候没有问题,但多线程可能会导致有些线程获取没有初始化完成的实例。这时候就需要volatile,它可以禁止jvm的指令重排
六.静态内部类实现(线程安全)
1.外部类Singleton被加载的时候,SingletonHolder并没有被加载 ,调用getxx()方法的时候,才会运行并加载静态内部类,然后初始化实例,此时靠jvm来保证只被实例化一次
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}
七.枚举类实现
public enum Singleton {
INSTANCE;
//添加自己需要的操作
public void doSomeThing() {
}
}
八.使用场景
频繁实例化然后又销毁的对象,使用单例模式可以提高性能。
经常使用的对象,但实例化时耗费时间或者资源多,如数据库连接池,使用单例模式,可以提高性能,降低资源损坏。
使用线程池之类的控制资源时,使用单例模式,可以方便资源之间的通信。