eec icon indicating copy to clipboard operation
eec copied to clipboard

fix: 修复并发导出计算列标时cache被错误修改

Open gaecfov opened this issue 1 year ago • 5 comments

现在默认缓存200列的下标,超过后使用当时计算的下标

(cherry picked from commit d64b169e391ccc40323980759791ce3a90012949)

gaecfov avatar Jun 07 '24 05:06 gaecfov

EEC从设计初就未考虑支持多线程的情况,如果要支持多线程Styles、SharedString、RowBlock甚至WorksheetWriter都需要重新设计,仅改这一个方法是不能满足多线程的,这个方法如果要改的话只需要将cache删掉即可,将里面c = cache[n]语句改为c = new char[n]即可,不需要缓存200个下标

无论是读还是写EEC都不支持多线程

wangguanquan avatar Jun 07 '24 07:06 wangguanquan

其他的没有细看,当前这个问题是多个用户导出时,写字段式计算的会错误,这个即使不是并发可能会存在问题,cache 也可能被前一个操作处理,这里的 cache 本身应该是不可变的

gaecfov avatar Jun 07 '24 10:06 gaecfov

能否将使用详细描述一下场景以及相关代码示例,我需要复现一下问题

wangguanquan avatar Jun 08 '24 02:06 wangguanquan

能否将使用详细描述一下场景以及相关代码示例,我需要复现一下问题

我重新看了下cache单线程应该没问题,cache 本身的值没什么作用,只是地址占位,具体的值还是当时算的

gaecfov avatar Jun 11 '24 01:06 gaecfov

能否将使用详细描述一下场景以及相关代码示例,我需要复现一下问题

我重新看了下cache单线程应该没问题,cache 本身的值没什么作用,只是地址占位,具体的值还是当时算的

是的,这里定义为cache容易产生歧义,定义为buffer更好理解,它的作用是将数字转为Excel的列号,这里并没有缓存的作用,因为每一行都需要计算完整的列号,比如10万行20列则需要计算10万x20次列号,所以这里为了减少实例化char[]才这么设计的。

缓存列号是可行的,不需要独立缓存只需要将列号缓存到Column中即可,你可以按下面这几个步骤重新修改并提交。

  1. Column新增列号属性realCol
  2. 删除Sheet#cache定义,直接在int2Col方法中new char[]
  3. 修改Sheet#calculateRealColIndex方法和WorksheetWriter#getColumn方法,在设置realColIndex后计算列号并保存到Column
  4. 修改WorksheetWriter#write方法中的int2Col(hc.getRealColIndex()),直接从Column获取列号

另外你可以实测一下是否能提升性能,个人估计影响不大

wangguanquan avatar Jun 11 '24 02:06 wangguanquan