zoukankan      html  css  js  c++  java
  • 线程并发安全导致内存溢出

    整个网站访问不了,后台日志内存溢出,提出了个致命单,找到问题后,整理成了案例,供培训使用。

    原因:

    流量统计FlowUtil类使用两个static的List来装载流量信息实体bean。
          用户每次点击都会将一个产生一个bean并加入到第一个List1中,当List1里的bean到一定数量时(可在后台配置缓存大小),List1将所有的实体bean复制到 List2中,然后List1清空继续接收新的bean,这时List2开启一个新线程异步去将bean插入数据库,然后清空。

    Method add(bean){

    list1.add(bean);

            if (list1.size() >= cacheSize)

            {

                List2.addAll(list1);

                list1.clear();

                new Thread({

                    try

    {

    insertDB(list2);

    list2.clear();

    }

                     catch (ApplicationException e)

                      {

                      }

    }).start();

            }

    }
          整个操作没有做同步锁定,如果并发量大,List2还没完成插入数据库的操作,List1又将新接收的bean全部加入到List2中,又发起一个新线程去插数据库,如果这个线程跑在之前那个线程前,因为这时List2之前的bean是没有被清空的,再插入数据库的时候,id就会重复,就会抛出违反唯一性约束异常,就不会执行下一行清空List2的代码,直接结束了。以后无论如何,每次操作都会抛出违反唯一性约束异常了,这个时候List2就会不断地接收List1传进来的bean,直到内存溢出。

    分析:如果在try-catach后的finally里去clear清空list2,不会出现这种现象,但也有线程安全问题。这段代码存在两个问题,一个是线程安全,一个就是try-catach段代码,没考虑到异常的情况,在try里每段代码都应考虑如果执行到这段会不会有影响,如果有就在finnally里执行。

    解决方案:同步数据转交那段代码,并不再使用static的List2,List1每次转交都给一个全新的List去执行插数据库。

    Method add(bean){

    list1.add(bean);

            if (list1.size() >= cacheSize)

            {   

                List list2 = new List();

                Synchronized{

    list2.addAll(list1);

                      list1.clear();

                }

                new Thread({

                    try

    {

    insertDB(list2);

    }

                     catch (ApplicationException e)

                      {

                      }

    }).start();

            }

    }
    由于每次都使用一个新的list2,也就不用再清空了。

  • 相关阅读:
    纯JavaScript实现HTML5 Canvas六种特效滤镜
    玩转html5 的 canvas画图
    为什么 ++[[]][+[]]+[+[]] = 10?
    作用域和闭包
    7 个令人惊讶的 JavaScript “特
    60个有用css代码片段
    函数
    数组
    我们为什么要尝试前后端分离
    javascript面向对象——构造函数和原型对象
  • 原文地址:https://www.cnblogs.com/onlywujun/p/2938211.html
Copyright © 2011-2022 走看看