私は、リクエストごとにいくつかの情報(クライアントIPアドレスなど)をいくつかのコレクションに保存するWebアプリケーションを持っています。時々私はそれを空にする必要があります、すべての要素をXMLにシリアル化し、XMLを他のWebサービスに送信します。作成してリクエストごとに1つのXMLを送ることができましたが、むしろデータをチャンクで送信することになりました(ウェブサービスとあまり頻繁に通信しないように)。コレクションの最大サイズ(outofmemoryerrorを除く)、ファイルを送信する必要がある期間、最小/最大ファイルサイズに関する要件はありません。また、jvmがクラッシュし、メモリに保存されているすべてのデータが失われることもあります。多くのプロデューサーと1人の消費者が一斉にすべてのメッセージをポーリングする
多くのスレッド(サーブレットコンテナによって生成されたスレッド)がコレクションに要素を追加し、しばらくしてコレクションからすべての要素をフェッチし、XMLにシリアル化してファイルを送信することを理解します。あなたはそのデザインをお勧めできますか?
コンシューマスレッドでビジー待機を使用する必要がありますか? コレクションのサイズが最大/しきい値サイズかどうかを確認するスレッド(プロデューサまたはコンシューマ)はどれですか? コレクションで同期を使用し、プロデューサ側でnotifyAllを使用してコンシューマに通知することはできますか? コンシューマ側でsynchronizeとwhile(size < MAX){wait()}を使用する必要がありますか? ドレインはListよりも優れていますtemp = new ArrayList <>(コレクション); ?
これは私の最初の考えです。代わりに、独自の圧延
public void add(Info info){
synchronized (collection) {
collection.add(info);
if (collection.size() > THRESHOLD) {
collection.notify();
}
}
}
public void send(){
while (true) {
List<Info> temp = null;
synchronized (collection) {
try {
collection.wait();
} catch (InterruptedException e) {
}
List<Info> temp = new ArrayList<>(collection);
collection.clear();
}
serializeAndSend(temp);
}
}
この場合、LinkedBlockingQueueは何も変更しません(take/drainToは、特定のしきい値サイズが必要な場合にのみ呼び出されます)。 – user1051075
@ user1051075 - 私の答えのアップデートをご覧ください。 (コメントの代わりに長さを付けてください) – ziesemer