项目实战典型案例7——在线人员列表逻辑混乱反例

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 项目实战典型案例7——在线人员列表逻辑混乱反例

在线人员列表逻辑混乱反例

一:背景介绍

本篇博客是对在线人员列表逻辑混乱反例进行的总结和进行的改进。

目的是将经历转变为自己的经验。通过博客的方式分享给大家,大家一起共同进步和提高。

在线人员列表逻辑混乱反例中涉及到的问题

  1. 类中写了公共变量最后导致数据混乱现象
  2. 保存数据没有考虑业务的隔夜覆盖导致的逻辑漏洞
    涉及到继承,对于this,如果父类有同样的成员最终使用哪一个?
  3. 参数不一致导致后续维护混乱
  4. mysql由于关联字段类型不一致导致产生索引失效问题,进而产生慢sql
  5. sql不考虑业务导致有明显的逻辑漏洞
    上面的问题主要分为四类问题:
  6. 公共变量导致数据混乱
  7. 对于在线人员的业务存在逻辑问题(对应上面的 2 4 6 )
  8. 面向对象继承的问题,this.属性和方法的问题
  9. mysql由于关联字段类型不一致导致索引失效的问题。

二:思路&方案

类中写了公共变量最后导致数据混乱现象的解决方案


由于线程共享全局变量,并且在实际业务的过程中对全局变量进行了操作(修改),所以在高并发、多线程的条件下会产生公共变量导致数据混乱的现象。

解决方案1 使用ThreadLocal

ThreadLocal叫做线程变量,该变量对于其他线程而言是隔离的,该变量是当前该线程独有的变量。

它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。正是由于每个线程都有自己的实例副本,且与其他线程不可访问,那就不存在多线程共享该变量的问题。

ThreadLocal 常见使用场景

1、每个线程需要有自己单独的实例

2、实例需要在多个方法中共享,但不希望被多线程共享

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 4 5 7 )的方案


解决思路:由于这里查询的入参带了createDate,如果该学生从第一天到第二天一直没有下课,那么你这儿查询的话由于带了createDate就查询不到该学生的在线数据,在后续的流程中就会重复插入,该学生就会有两条数据,查询的时候就会有数据问题。


解决思路: 对于isOnline参数,上面paramUser中有该参数。不必再进行赋值。这样的好处是参数值保持了一致,降低了复杂度。


**解决思路:**这里主要是对在线人员进行下线处理,1.如果在这里更新了update_time那么就相当于这个课程班级中的所有学生的最近一次登陆时间都是一致的,并且最近一次登陆时间与实际不符。2.如果where条件上加上了create_date作为条件那么如果过了十二点结束课程,那么所有在线的人就无法进行下线处理了。

正确的SQL语句:



面向对象继承的问题

解决思路: 1.子类可以继承父类的所有非private修饰的属性和方法 2.this.方法的问题


面向对象子类与父类中this的使用

实例结构


动物类

public class Animal {
    protected String name="动物" ;
    protected String age="18";
    public void printName(){
        System.out.println(name);
    }
    public void printAge(){
        System.out.println(age);
    }
}

猫类

public class Cat extends Animal {
 private String name="猫";
  public void printName(){
    System.out.println(this.name);
    System.out.println(super.name);
  }
  public void println(){
    this.printName();
    super.printName();
  }
}

调用类

public class Client {
    public static void main(String[] args) {
        Cat cat =new Cat();
        cat.printName();
        cat.printAge();
        cat.println();
    }
}

实现结果


结论:

java中继承关系的父子类,相同的方法会被重写

当子类父类中的成员没有重名时,子类都可以通过this去调用。
成员方法 重名,子类就会将父类中的方法进行重写。如果还想调用父类中的方法只能通过 super去进行调用。

当时成员变量不存在覆盖重写:在子类中只能通过super调用父类的

mysql由于关联字段类型不一致导致索引失效的问题的解决方案

在实际的项目开发过程中,需要特别注意关联字段的数据类型是否一致。吐过不一致将导致索引失效,出现mansql的情况。

索引失效的问题复现

EXPLAIN SELECT
aui.ding_phone,
aui.ding_name,
aui.chaoxing_name,
aui.chaoxing_phone
FROM
(SELECT info_id FROM `arpro_user_course_info` WHERE course_id = '223667994' AND class_id = '55801765' AND is_delete = 0 GROUP BY id)as auci
left JOIN arpro_user_info as aui on auci.info_id=aui.id

arpro_user_course_info与arpro_user_info通过info_id与aui.id进行主外键的关联。

arpro_user_info的id类型为varchar类型


arpro_user_course_info的info_id类型为bigint类型


通过EXPLAIN进行sql语句的性能分析

发现arpro_user_info的为全部查询,索引失效了。



将关联字段的类型修改为一致再次进行测试

测试结果

索引生效


四:总结

1.在项目开发过程中,对于公共变量的使用一方面需要慎重,需要考虑是否有并发,多线程的情况,然后根据实际情况选择对应的处理措施。
2.关于项目开发过程中出现的逻辑问题,一方面进行开发一定需要绘制流程图,根据流程图进行代码编写,另一方面及时总结将经历转变为经验。

3.对于面向对象中子类父类的的特点,一方面进行理论学习,一方面特别需要进行实践验证。

4.关于sql语句由于级联关联字段类型不一致,出现索引失效的问题需要特别重视,极易出现性能问题。也需要了解其他情况下索引失效。

五:升华

  1. 闭环反馈,是成长型思维的核心
  2. 不怕不知道就怕不知道,扩大认知圈


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
程序员
程序员必知!里式替换原则的实战应用与案例分析
里式替换原则(Liskov Substitution Principle, LSP)是面向对象设计的基本原则之一,由Barbara Liskov于1987年提出。这个原则的主要思想是:在软件中,如果一个类可以被另一个类所替换,并且不会影响程序的正确性,那么这两个类就遵循了里式替换原则。
程序员必知!里式替换原则的实战应用与案例分析
|
1月前
|
机器学习/深度学习 监控 机器人
量化交易机器人系统开发逻辑策略及源码示例
量化交易机器人是一种通过编程实现自动化交易决策的金融工具。其开发流程包括需求分析、系统设计、开发实现、测试优化、部署上线、风险管理及数据分析。示例中展示了使用Python实现的简单双均线策略,计算交易信号并输出累计收益率。
|
5月前
|
机器学习/深度学习 监控 算法
量化交易系统开发步骤功能/规则玩法/案例项目/逻辑功能
量化交易策略系统开发是指利用编程和数学模型来设计、开发和实施自动化交易策略的过程。它涉及了将交易策略转化为可编程的算法,以便计算机可以根据预定规则和条件进行自动交易。
|
5月前
|
运维 监控 安全
软件研发核心问题之用在需求拆解时明确监控范围与形式的问题如何解决
软件研发核心问题之用在需求拆解时明确监控范围与形式的问题如何解决
|
5月前
软件研发核心问题之在需求拆解过程中,“数据与UI如何关联”的问题如何解决
软件研发核心问题之在需求拆解过程中,“数据与UI如何关联”的问题如何解决
|
7月前
|
C++ Python
量化交易系统开发详细步骤/需求功能/策略逻辑/源码指南
Developing a quantitative trading system involves multiple steps, and the following is a possible development process
游戏对接广告看视频系统开发详细规则/方案逻辑/步骤逻辑/规则玩法/源码程序
Advertising location and display method: According to the characteristics of the game interface and scene, choose the appropriate advertising location and display method to ensure that the advertisement naturally integrates into the game and does not affect the player&#39;s game experience.
|
7月前
|
人工智能 算法 测试技术
【简历优化平台-03】轻字段信息的合理性及单独算法
【简历优化平台-03】轻字段信息的合理性及单独算法
|
Cloud Native 前端开发
【性能优化上】第三方组织结构同步优化一,分状态,分步骤的设计,你 get 到了吗?
【性能优化上】第三方组织结构同步优化一,分状态,分步骤的设计,你 get 到了吗?
|
安全 Go 区块链
区块链游戏链游系统开发功能详情丨方案逻辑丨开发项目丨案例分析丨源码规则
 In recent years, with the continuous development of blockchain technology, NFTs (non homogeneous tokens) and DAPPs (decentralized applications) have emerged in the gaming industry.