【发布时间】:2015-09-28 14:55:39
【问题描述】:
当多个线程通过 RMI 访问同一服务器时,我的程序遇到了问题。服务器包含一个列表作为缓存并执行一些昂贵的计算,有时会更改该列表。计算完成后,列表将被序列化并发送给客户端。
第一个问题:如果列表在序列化时发生更改(例如,由不同的客户端请求某些数据)ConcurrentModificationException(可能)被抛出,导致 RMI 的EOFException在客户端调用/反序列化。
因此,我需要某种列表结构,它对于序列化是“稳定的”,同时可能被不同的线程更改。
我们尝试过的解决方案:
- 常规 ArrayList / Set - 由于并发而无法正常工作
- 在每次序列化之前深度复制整个结构 - 太贵了
-
CopyOnWriteArrayList- 也很昂贵,因为它复制了列表和
揭示第二个问题:我们需要能够原子地替换列表中当前不是线程安全的任何元素(先删除,然后添加(更昂贵))或只能通过锁定列表来实现,因此只能按顺序执行不同的线程。
因此我的问题是:
您知道
Collection实现,它允许我们serialize集合线程安全,而其他线程修改它and,其中包含某种方式的atomically replacing元素?如果列表在序列化之前
not需要是copied,那将是一个奖励!为每个序列化创建一个快照是可以的,但仍然是 meh :/
问题说明(C=计算,A=添加到列表,R=从列表中删除,S=序列化)
Thread1 Thread2
C
A
A C
C A
S C
S R <---- Remove and add have to be performed without Thread1 serializing
S A <---- anything in between (atomically) - and it has to be done without
S S blocking other threads computations and serializations for long
S and not third thread must be allowed to start serializing in this
S in-between state
S
【问题讨论】:
-
删除后添加时,替换是否必须在列表末尾?
-
@PaulBoddington 不,顺序无关紧要,我们也可以使用 Set。
-
删除是什么意思?你是删除已知索引的元素(如
remove(index))还是使用搜索和删除(如remove(Object))? -
@TagirValeev
replaceWithObj(Object, Object),不是通过索引,而是通过检查每个对象是否相等。目前通过调用remove(Object)然后add(slightlyDifferentObj)
标签: java multithreading serialization collections copyonwritearraylist