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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 项目实战典型案例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. 不怕不知道就怕不知道,扩大认知圈


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 供应链 安全
dapp系统开发详细规则/玩法功能/案例设计/源码步骤
DApp是指去中心化应用(Decentralized Application),是构建在区块链技术之上的应用程序。与传统的中心化应用不同,DApp不依赖于中心化的服务器或管理者,而是通过智能合约和分布式网络来实现去中心化的运行。
|
7月前
|
安全
dapp互助预约排单系统开发步骤指南/案例设计/规则详细/方案逻辑/源码程序
-Determine the core functions and objectives of the system, understand user needs and expectations.
预约抢单互助系统开发详细功能/需求方案/步骤功能/逻辑项目/源码案例
The development model of appointment and order grabbing mutual assistance system is a widely used development model on mutual assistance service platforms. It adopts a combination of appointment and order grabbing modes, allowing users to make appointments or actively participate in mutual assistanc
|
8月前
|
安全
交易所系统开发规则案例丨需求分析丨功能设计丨详细步骤丨源码逻辑
Before developing a digital currency exchange system, a detailed requirement analysis is required. Firstly, it is necessary to clarify the types of digital currencies and trading varieties that the system needs to support. Secondly, it is necessary to determine the user roles and permission manageme
|
6月前
|
存储 开发框架 安全
dapp去中心化大小公排项目系统开发案例详情丨规则玩法丨需求逻辑丨方案项目丨源码程序
区块链技术的去中心化应用(DApp)开发在近年来逐渐受到广泛关注。大小公排互助系统是一种较为流行的DApp模式之一,其基本特点是参与者按照加入顺序依次排队,
|
7月前
|
存储 前端开发 安全
什么是盲盒游戏系统开发规则丨指南教程丨功能逻辑丨需求项目丨源码方案
确定盲盒游戏的目标受众、玩法要素和游戏规则。 - 确定游戏系统的核心功能,如盲盒的获取、开启、物品收集、交易等。 - 确定技术平台和开发语言,如移动端应用的开发是选择原生开发(如iOS的Swift或Android的Java/Kotlin)还是跨平台开发(如React Native或Flutter)。
|
7月前
|
安全
交易所系统开发详细项目丨案例规则丨方案设计丨步骤需求丨逻辑功能丨源码程序
Requirement analysis and planning: Collaborate with customers to clarify the requirements and goals of the coin exchange system. Understand the customer&#39;s business model, target user group, and currencies to be supported by the exchange, and develop a detailed demand plan.
|
8月前
|
安全 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.
|
8月前
|
存储 安全 区块链
区块链游戏系统开发(开发详细)/案例开发/设计功能/逻辑方案/源码平台
  区块链游戏系统开发是一个复杂而精密的过程。首先,需要进行需求分析和规划,确定游戏系统的功能和特性。然后,进行技术选型和架构设计,选择适合的区块链平台和开发工具。接下来,进行系统的搭建和编码,实现游戏逻辑和用户交互功能。最后,进行测试和优化,确保系统的稳定性和性能。
|
9月前
|
SQL 安全 Java
【项目实战典型案例】07.在线人员列表逻辑混乱反例
【项目实战典型案例】07.在线人员列表逻辑混乱反例

热门文章

最新文章