2012-02-01 2 views
2

私は、リクエストごとにいくつかの情報(クライアント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); 
    } 

}

答えて

2

、少なくともLinkedBlockingQueueまたはjava.util.concurrentから何か他のもののようなものを使用することを検討してください:私はそれを批判する理由のたくさんがあると確信しています。

同様に、notify()wait()の呼び出しが同じオブジェクトに対して機能していないため、現在のコードは機能しません。

あなたの要件は興味深いものです。何らかの理由でJVMが消滅し、キューに入れられたすべてのデータが失われた場合はどうでしょうか?とにかく、あなたのコメントに続いて - これまでと同じようなことをやっておくことができます - カスタムメソッドですべての追加操作をフィルタリングし、コレクションが特定のサイズに達したらserializeAndSend。しかし、このアプローチに従えば、並行処理をサポートするコレクションは本当に必要ありません。 collection.wait()を呼び出すようにコードを更新したこともわかります。これは良いことです。

+0

この場合、LinkedBlockingQueueは何も変更しません(take/drainToは、特定のしきい値サイズが必要な場合にのみ呼び出されます)。 – user1051075

+0

@ user1051075 - 私の答えのアップデートをご覧ください。 (コメントの代わりに長さを付けてください) – ziesemer

関連する問題