entityMap的用法有些问题,synchronized关键字的用法也存在瑕疵。 1. 先说一下entityMap,楼主对 ConcurrentHashMap 的理解还是存在问题,这个Map是线程安全的类,只能保证它的单独一次调用是线程安全的,也就是说它的锁区间只包含在单个的方法调用期间。 楼主在使用 entityMap 的过程中,是先调用了 containsKey 函数,然后才是 get 或者 put 方法,这种用法的逻辑思路很清晰,但是,你忽略了一点,就是它的锁不是上在if块上的,只在单独的 containsKey 函数调用期间有锁保护(单独的get/put调用也一样),所以,代码的保护区间出现了问题。造成的后果是:相同batchKey的两个线程,一个线程调用完 containsKey 返回false之后被切换出去,另一个线程也调用 containsKey 函数,也会返回 false,因为第一个线程的if块不是整体锁保护的,在执行完containsKey函数之后,是可以被切换出去的。然后,两个线程都会执行false条件下的代码块,创建了两个ArrayList,当然,先创建的ArrayList会被后创建的覆盖掉,从而造成数据的丢失。 2. List<CouponEntity> list 的用法也存在问题。多线程状况下,没有对核心数据操作进行锁保护,一个线程执行完 sendPostRequest 函数后别切换出去,另一个线程已然可以对相同的list进行sendPostRequest调用,因为前一个线程没有调用clear方法,list里面仍然有数据,从而造成数据的重复发送。 3. 为啥最后说这个 synchronized 呢? 因为,exeKafka 方法上的同步关键字,它的锁对象不是 entityMap ,所以,后面那个在 entityMap上面使用同步关键字的代码,失去了意义。两个不同的锁对象,代表两个独立的锁保护机制。正确的做法应该是对同一个对象进行上锁,然后,保护这个对象的多个数据操作代码,从而达到同一时刻只能有一个线程进入被保护的其中一个代码块,达到线程安全的目的。 额外解释一下:为啥 exeKafka 函数已经上锁了,为啥还会出现数据问题呢? 关键就在于你只保证了同一时刻只有一个线程在调用exeKafka函数,但是,目前的synchronized关键字的用法,你无法保证一个线程在执行exeKafka函数时,其他线程不能调用timerSend函数啊。如果有两个线程同时分别调用exeKafka函数和timerSend函数,会产生什么结果? 看看我1和2说的内容,你品,你细品~
你是服务器是集群还是单机,要是集群的话就是加synchronized 也是不行的,建议使用redis锁,或者zk锁,还有你@scheduled的定时任务的里面的hashmap 最好换为ConcurrentHashamp试试
你是怎么用synchronized的?在用到entityMap的地方加synchronized(entityMap)获得锁后再使用entityMap 另外,你的entity是在哪里取得的?取得的条件是什么,有没有可能重复取得数据?
你搞个临时表,接收到的数据直接插表。再搞个job扫描临时表,取1000条发,发完了删除或者标记删除。JOB 30秒执行一次,不就行了吗
引用 9 楼 苏颙 的回复:这代码写的 槽多无口,直接取出来数据不足 1000 直接扔到调度线程池,大于 1000 直接发送就完事了,整个全局变量肯定有问题啊不用全局变量,kafka推过来的数据,如何知道条数?
这代码写的 槽多无口,直接取出来数据不足 1000 直接扔到调度线程池,大于 1000 直接发送就完事了,整个全局变量肯定有问题啊
全局容器没问题,关键你的任务调度逻辑有些不清楚 1000&30s 这两个条件以先到的为准 执行发送下游数据 过后开始下一个运作周期是吧? 推荐使用 juc下 condition 完成这段逻辑 比你这清晰多了
67,512
社区成员
225,885
社区内容
加载中
试试用AI创作助手写篇文章吧