我第二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