【项目实战典型案例】15.登录之后我加入的课程调用接口报错

目录

  • 一:背景介绍
    • 问题一:出现域名不全的情况,和加载到内存的全部变量有关。如果存入redis的值一旦错误,一天内都会出现这样的情况
    • 问题二:每一次登录都会重新创建一个对象,放到公共变量中,如果遇到了并发,这里的对象将会被大量的创建,然后上一个对象会失去引用,等待垃圾回收器回收,从而会导致cpu飙升
  • 二:问题复现
    • 数据混乱现象复现
      • 计算类
      • 客户端类
      • 实现结果
  • 三:优化过程
    • 问题一
      • 使用ThreadLocal
        • 计算类
        • 实现效果
      • 使用synchronized进行
    • 问题二
      • 调用removeALL()方法
  • 四:总结

一:背景介绍

问题一:出现域名不全的情况,和加载到内存的全部变量有关。如果存入redis的值一旦错误,一天内都会出现这样的情况

【项目实战典型案例】15.登录之后我加入的课程调用接口报错_第1张图片

问题二:每一次登录都会重新创建一个对象,放到公共变量中,如果遇到了并发,这里的对象将会被大量的创建,然后上一个对象会失去引用,等待垃圾回收器回收,从而会导致cpu飙升

【项目实战典型案例】15.登录之后我加入的课程调用接口报错_第2张图片

二:问题复现

数据混乱现象复现

计算类

public class ThreadTest {
    List<String> threadList = new ArrayList<>();

    public void ThreadList1(){
        threadList = new ArrayList<>();
        threadList.add("1");
        threadList.add("2");
        threadList.add("3");
        threadList.add("4");
        System.out.println("ThreadList1"+threadList);
    }

    public void ThreadList2(){
        threadList = new ArrayList<>();
        threadList.add("a");
        threadList.add("b");
        threadList.add("c");
        threadList.add("d");

        //看一下list里有什么
        System.out.println("ThreadList2"+threadList);
    }
}

客户端类

public class Client {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    threadTest.ThreadList1();
                    threadTest.ThreadList2();
                }
            });
            thread.start();
        }
    }
}

实现结果

出现了数据混乱的情况
【项目实战典型案例】15.登录之后我加入的课程调用接口报错_第3张图片

三:优化过程

问题一

使用ThreadLocal

计算类

public class ThreadTest {
    private static ThreadLocal<List<String>> threadList = new ThreadLocal<List<String>>(){
        @Override
        public List<String> initialValue(){
            return new ArrayList<String>();
        }
    };
    public void ThreadList1(){
        threadList.get().add("1");
        threadList.get().add("2");
        threadList.get().add("3");
        threadList.get().add("4");
        System.out.println("ThreadList1"+threadList.get());
    }
}

实现效果

【项目实战典型案例】15.登录之后我加入的课程调用接口报错_第4张图片

使用synchronized进行

synchronized保证方法某一时刻只有一个线程去执行,从而保证线程安全性
synchronized可以修饰方法,对象实例,某个类,代码块

public class ThreadTest {
    List<String> threadList = new ArrayList<>();

    public synchronized void ThreadList2(){
        threadList = new ArrayList<>();
        threadList.add("a");
        threadList.add("b");
        threadList.add("c");
        threadList.add("d");

        //看一下list里有什么
        System.out.println("ThreadList2"+threadList);
    }
}

【项目实战典型案例】15.登录之后我加入的课程调用接口报错_第5张图片

问题二

调用removeALL()方法

public class ThreadTest {
    List<String> threadList = new ArrayList<>();

    public synchronized void ThreadList2(){
        threadList = new ArrayList<>();
        threadList.add("a");
        threadList.add("b");
        threadList.add("c");
        threadList.add("d");

        //看一下list里有什么
        System.out.println("ThreadList2"+threadList);
        threadList.removeAll(threadList);
    }
}

四:总结

  1. 在项目开发过程中,对于一些公共变量的使用要慎重,需要考虑是否有并发,以及多线程的情况
  2. 编写代码的时候,要清楚为什么要这么写

你可能感兴趣的:(java,jvm,算法)