Ben işlemlerini yönetmesine izin vermek için bana mantıklı Bir veritabanının ikinci Telcontar's suggestion numaralı sürümü, aslında bu veri ölçeğini yönetmek ve iş parçacıkları arasında görüşme yapmak için tasarlandığından, bellek içi koleksiyonlar olmadığından.
Verilerin sunucudaki bir veritabanında olduğunu ve istemcilerdeki yerel listenin kullanıcı arabirimi uğruna olduğunu söylüyorsunuz. İstemcideki tüm 100000 öğeyi bir kerede saklamanız veya üzerinde karmaşık düzenlemeler yapmanız gerekmemelidir. Bana öyle geliyor ki, istemcide istediğiniz şey veritabanına hafif bir önbellek.
Yalnızca istemcideki geçerli veri alt kümesini bir kerede depolayan bir önbellek yazın. Bu istemci önbelleği, kendi verileri üzerinde karmaşık çok iş parçacıklı düzenlemeler gerçekleştirmez; bunun yerine, tüm düzenlemeleri sunucuya besler ve güncelleştirmeleri dinler. Veriler sunucuda değiştiğinde, istemci sadece eski verileri ve eski verileri unutur ve tekrar yükler. Koleksiyonun kendisinin sadece bir atanmış ipliği okumasına veya yazmasına izin verilir. Bu şekilde istemci, karmaşık düzenlemelere gerek kalmadan sunucu üzerinde gerçekleşen düzenlemeleri basitçe yansıtır.
Evet, bu oldukça karmaşık bir çözümdür. bunun bileşenleri şunlardır:
oldukça şeyi
- değişti verilerin
- bir önbellek sınıfı hakkında güncellemeler almak için bir protokol yerine, ürün 478712 için 478901 veri aralığı yüklenmesi için bir protokol söylemek
- Bu, öğeleri sunucudaki bilinen dizine göre depolar
- Sunucuyla iletişim kuran bu önbelleğe ait bir iş parçacığı. Bu koleksiyon kendisi yazar tek iplik
- veri
- o yüklendiğinde UI bileşenleri bunları veri alma için izin uygulamak bir arayüz alındığında geri aramalar işleyen bu cache ait bir iş parçacığı
ilk bıçak başta
, bu önbellek kemikleri şöyle görünebilir: belli ki, kendiniz için doldurmak gerekecek detay çok şey var
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();
}
.
import java.util.Collections;
import java.util.ArrayList;
ArrayList list = new ArrayList();
List syncList = Collections.synchronizedList(list);
// make sure you only use syncList for your future calls...
Bu kolay bir çözümdür:
ConcurrentSkipListMap fikrini beğeniyorum. Zamanın% 90'ında liste, bazı zaman damgalarına (her alanın kimliğinin bir kısmına) göre sıralanır, bu yüzden muhtemelen bunun için optimizasyona değer. Hala diğer% 10'u düşünecek. –