五、设计模式调优
单例模式
最简单的单例模式及问题分析
// 懒汉模式
public final class Singleton {
private static Singleton instance= null;// 不实例化
private Singleton(){
if (instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}
}// 构造函数
public static Singleton getInstance(){// 通过该函数向整个系统提供实例
if(null == instance){// 当 instance 为 null 时,则实例化对象,否则直接返回对象
instance = new Singleton();// 实例化对象
}
return instance;// 返回已存在的对象
}
}
问题分析:存在多次实例化的可能,多个线程同时修改不同单例对象可能导致数据不一致,因为单例对象可能持有计数器或者配置项等。
先创建的对象会不会被jvm垃圾回收?
可能会,前提是没有被其他对象引用,如创建并使用他的线程结束,该对象就不会被引用,下一次垃圾回收就会回收掉。
双重检查方式:
// 懒汉模式 + synchronized 同步锁 + double-check
public final class Singleton {
private volatile static Singleton instance= null;// 不实例化
private Singleton(){
if (instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}
}// 构造函数
public static Singleton getInstance(){// 加同步锁,通过该函数向整个系统提供实例
if(null == instance){// 第一次判断,当 instance 为 null 时,则实例化对象,否则直接返回对象
synchronized (Singleton.class){// 同步锁
if(null == instance){// 第二次判断
instance = new Singleton();// 实例化对象
}
}
}
return instance;// 返回已存在的对象
}
}
双重检查模式的变量需要用volatile,volatile有两个作用:可见性,禁止指令重排序。
静态内部类方式:
// 懒汉模式 内部类实现
public final class Singleton {
// 构造函数
private Singleton() {
if (InnerSingleTon.instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}
}
// 内部类实现
public static class InnerSingleton {
private static Singleton instance=new Singleton();// 自行创建实例
}
public static Singleton getInstance() {
return InnerSingleton.instance;// 返回内部类中的静态变量
}
}
静态内部类和外部类的加载是独立的,外部类被加载时,静态内部类不会被立即加载。静态内部类只有在被主动引用时(例如创建静态内部类的实例或访问其静态成员)才会被加载。同样地,当静态内部类被加载时,它也不会导致外部类重新加载或初始化。
装饰器模式
六、数据库性能调优
快照读:当执行普通的select时,mysql不会加锁,而是读取数据库快照,在整个事务生命周期都是获取同一个快照数据,不糊收到其他事务更新或插入影响。快照并不是事务开始时的快照,而是第一次普通查询时被锁定的快照。
但是并不是每次查询结果不会变,如事务B插入一条原本不存在的数据,事务A修改了这条数据,此时事务A再查询是可以查到的。
当前读:当读取的是需要加锁的的操作,读取的是当前最新数据,当前读会阻止其他事务对被锁住的数据进行修改,并确保你看到的是最新的、当前事务的状态。
SELECT ... FOR UPDATE
SELECT ... LOCK IN SHARE MODE
UPDATE
和DELETE
间隙锁:需要注意mysql查询又间隙锁,即使只查询一条数据如order_no=4,数据分布是1,3,6,8,那么会锁定3到6之间的间隙,这种操作可以防止3-6之间的幻读。但是大于6的数据如7,20都是可以在另一个事务B中正常插入的,并且事务A中可以查到。
分库分表:
分为水平拆分和垂直拆分:水平拆分是把数据分布在不同库上,垂直拆分是指把表字段再进行拆分。
分布式锁:redis官方推出的redisson框架。
标签:Singleton,java,实例,记录,instance,调优,static,null,class From: https://www.cnblogs.com/gaoshikenan/p/18435345