我第二Telcontar's suggestion数据库,因为它们实际上是为管理这个数据的规模和线程之间的协商而设计的,而内存中的集合则不是。
你说数据在服务器上的数据库上,而客户端上的本地列表是为了用户界面。您不需要一次将所有100000个项目保留在客户端上,或对其执行如此复杂的编辑。在我看来,你想在客户端上的是一个轻量级缓存到数据库。
编写一个只存储客户端当前数据子集的缓存。此客户端缓存不会对其自己的数据执行复杂的多线程编辑;相反,它会将所有编辑提供给服务器,并侦听更新。当服务器上的数据发生变化时,客户端只会忘记旧数据并重新加载。只有一个指定的线程被允许读取或写入集合本身。通过这种方式,客户端仅仅反映了服务器上发生的编辑,而不需要复杂的编辑。
是的,这是一个相当复杂的解决方案。它的成分是:
- 一种用于装载各种数据的协议,说项目478712至478901,而不是整个事情
- 用于接收关于改变的数据
- 缓存类更新协议通过服务器上的已知索引存储项目
- 属于与服务器通信的高速缓存的线程。这是写入集合本身的唯一线程
- 属于该缓存时数据被检索
- 该UI组件实现,让他们收到数据时已经装好了一个接口,它处理回调线程
起初刺,这个缓存的骨头可能是这个样子:
class ServerCacheViewThingy {
private static final int ACCEPTABLE_SIZE = 500;
private int viewStart, viewLength;
final Map<Integer, Record> items
= new HashMap<Integer, Record>(1000);
final ConcurrentLinkedQueue<Callback> callbackQueue
= new ConcurrentLinkedQueue<Callback>();
public void getRecords (int start, int length, ViewReciever reciever) {
// remember the current view, to prevent records within
// this view from being accidentally pruned.
viewStart = start;
viewLenght = length;
// if the selected area is not already loaded, send a request
// to load that area
if (!rangeLoaded(start, length))
addLoadRequest(start, length);
// add the reciever to the queue, so it will be processed
// when the data has arrived
if (reciever != null)
callbackQueue.add(new Callback(start, length, reciever));
}
class Callback {
int start;
int length;
ViewReciever reciever;
...
}
class EditorThread extends Thread {
private void prune() {
if (items.size() <= ACCEPTABLE_SIZE)
return;
for (Map.Entry<Integer, Record> entry : items.entrySet()) {
int position = entry.key();
// if the position is outside the current view,
// remove that item from the cache
...
}
}
private void markDirty (int from) { ... }
....
}
class CallbackThread extends Thread {
public void notifyCallback (Callback callback);
private void processCallback (Callback) {
readRecords
}
}
}
interface ViewReciever {
void recieveData (int viewStart, Record[] records);
void recieveTimeout();
}
有很多你必须填写自己,很明显的细节。
我喜欢ConcurrentSkipListMap的想法。在90%的时间内,列表根据某个时间戳(每个域对象的ID的一部分)进行排序,所以它可能值得优化。仍然会考虑其他10%。 – 2008-10-17 08:10:23