一、背景介绍
在线人员列表涉及到的问题:
类中写了公共变量最后导致数据混乱现象
保存数据没有考虑业务的隔夜覆盖导致的逻辑漏洞
涉及到继承,对于this,如果父类有同样的成员最终使用哪一个?
参数不一致导致后续维护混乱
mysql由于关联字段类型不一致导致产生索引失效问题,进而产生慢sql
sql不考虑业务导致有明显的逻辑漏洞
上面的问题主要分为四类问题:
公共变量导致数据混乱
对于在线人员的业务存在逻辑问题(对应上面的 2 4 6 )
面向对象继承的问题,this.属性和方法的问题
mysql由于关联字段类型不一致导致索引失效的问题。
二、解决过程
1.类中写了公共变量最后导致数据混乱现象
原因:由于线程共享全局变量,并且在实际业务的过程中对全局变量进行了操作(修改),所以在高并发、多线程的条件下会产生公共变量导致数据混乱的现象。
方案:1.使用ThreadLocal
ThreadLocal叫做线程变量,该变量对于其他线程而言是隔离的,该变量是当前该线程独有的变量。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。正是由于每个线程都有自己的实例副本,且与其他线程不可访问,那就不存在多线程共享该变量的问题。
没使用ThreadLocal之前
代码编写
public class Client { public static void main(String[] args) { // 定义线程实现接口 Runnable runnable = new Runnable(){ Counter counter = new Counter(); @Override public void run() { counter.count(); } }; // 启动10个线程 for( int i= 0;i< 10;i++) { new Thread(runnable).start(); } } } public class Counter{ private int number; public void count(){ for (int i = 0; i <=10 ; i++) { number=number+i; } System.out.println(Thread.currentThread().getName()+ "--"+number; } }
执行结果:计算的结果应该都为55,结果出现了混乱的情况
使用ThreadLocal之后
public class Client { public static void main(String[] args) { // 定义线程实现接口 Runnable runnable = new Runnable(){ Counter counter = new Counter(); @Override public void run() { counter.count(); } }; // 启动10个线程 for( int i= 0;i< 10;i++) { new Thread(runnable).start(); } } } public class Counter { private static ThreadLocal<Integer> number = new ThreadLocal<Integer>() { // 重写这个方法,可以修改“线程变量”的初始值,默认是null @Override protected Integer initialValue() { return 0; } }; //计数方法 public void count() { for( int i= 0;i<= 10;i++) { number.set(number.get()+i); } System.out.println(Thread.currentThread().getName()+ "--"+number.get()); } }
执行结果
2.将全局变量改为成员变量
public void count(){ int number = 0; for (int i = 0; i <=10 ; i++) { number=number+i; } System.out.println(Thread.currentThread().getName()+ "--"+number); } }
2.逻辑混乱多种情况
由于这里查询的入参带了createDate,如果该学生从第一天到第二天一直没有下课,那么你这儿查询的话由于带了createDate就查询不到该学生的在线数据,在后续的流程中就会重复插入,该学生就会有两条数据,查询的时候就会有数据问题。
对于isOnline参数,上面paramUser中有该参数。不必再进行赋值。这样的好处是参数值保持了一致,降低了复杂度。
这里主要是对在线人员进行下线处理,1.如果在这里更新了update_time那么就相当于这个课程班级中的所有学生的最近一次登陆时间都是一致的,并且最近一次登陆时间与实际不符。2.如果where条件上加上了create_date作为条件那么如果过了十二点结束课程,那么所有在线的人就无法进行下线处理了。
3.父子类继承对于this的使用
java中继承关系的父子类,相同的方法会被重写。重写之后如果还想继续使用父类的方法,需要通过super关键字去调用父类的方法。
4.关联字段类型不一致导致索引失效
相关博客:(5条消息) 案例12-数据类型不一致导致索引失效_武梓龙_Arvin的博客-CSDN博客
三、总结提升
拓展我们的知识面,不怕不知道就怕不知道。知识面宽广了在解决问题,思考解决办法才能更丰富维度才会更多。