データベースに関するTelcontarの提案には賛成です。データベースは実際には、この規模のデータを管理し、スレッド間でネゴシエートするように設計されていますが、インメモリ コレクションはそうではありません。
データはサーバー上のデータベースにあり、クライアント上のローカル リストはユーザー インターフェイスのためのものだとおっしゃっています。一度に 100000 個のアイテムすべてをクライアントに保持したり、そのような複雑な編集を実行したりする必要はありません。クライアントに必要なのは、データベースへの軽量キャッシュであるように思えます。
クライアント上のデータの現在のサブセットのみを格納するキャッシュを一度に書き込みます。このクライアント キャッシュは、独自のデータに対して複雑なマルチスレッド編集を実行しません。代わりに、すべての編集をサーバーにフィードし、更新をリッスンします。サーバー上でデータが変更されると、クライアントは単純に古いデータを忘れて再度ロードします。指定された 1 つのスレッドのみが、コレクション自体の読み取りまたは書き込みを許可されます。このように、複雑な編集自体を必要とするのではなく、クライアントはサーバー上で行われている編集を単純にミラーリングします。
はい、これは非常に複雑なソリューションです。そのコンポーネントは次のとおりです。
- 全体ではなく、データの範囲、たとえば項目 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 ();
}
明らかに、自分で記入しなければならない詳細がたくさんあります。