0

を使用しており、 のリストを格納するバッファとして機能SpringMVCするクラスを持っています。リストのサイズが1000に達した後、すべてのクエリをデータベースに書き込みます。AServiceString

@Service
class AService    {
    List<String> list;

    public void addAndInsert(String query)  {
    list.add(query);
    if(list.size() >= 1000)    {
        writeIntoDatabase(list);
        list.clear();
    }

    }

}

これは、スレッドが 1 つしかない場合にうまく機能します。しかし、さまざまなユーザーからクエリを呼び出すことができることがわかっているので (もちろんマルチスレッドです)、これが適切に機能することを保証するにはどうすればよいでしょうか。

  1. クエリが 1000 に達したら、別のスレッドを使用してデータベースへの書き込みを実行したいと思います。この手順は長くなる可能性があるため、クエリに関係のないことをユーザーに待たせたくありません。

  2. クエリが失われたり、複製されたりすることはありません。

このシナリオにどのように対処すればよいか、どのListクラスの実装を使用すればよいか教えてもらえますか? ありがとう!

4

4 に答える 4

1

すべてのアクセスが同期されていて、挿入スレッドに渡す前にコピーを作成していれば、ArrayList は問題なく動作します。

@Service
class AService    {
    private List<String> list = new ArrayList<>(1000);

    public synchronized void addAndInsert(String query)  {
        list.add(query);
        if (list.size() >= 1000) {
            List<String> copy = new ArrayList<>(list);
            writeIntoDatabase(copy);
            list.clear();
        }
    }
}

ただし、クエリが失われないことが重要な場合は、バッファを使用しないでください。明らかに、リストに 999 個の要素が含まれているときにサーバーがクラッシュすると、999 個のクエリが失われるからです。

于 2013-11-11T12:09:09.783 に答える
0

Robsの回答に基づいて、DBへの挿入が一度に1000クエリに対して行われることを確認したいと思います。したがって、すべての同期を処理するBlockingQueues (ArrayBlockingQueueまたは など) を使用できます。また、ブロッキング キューから指定された数の要素を取得し、writeIntoDataBase に使用できる別のコレクションにそれらを返す のLinkedBlockingQueueようなメソッドも取得します。drainToのように

BlockingQueue<String> list;

public void addAndInsert(String query)  {
    list.add(query);
    if ( list.size() >= 1000) {
        int size = 1000;
        final ArrayList<String> toInsert = new ArrayList<String>( 1000);
        list.drainTo( toInsert, size);
        executorService.execute( new Runnable() {
            public void run() {
                writeIntoDataBase( toInsert);
            }
        });
    }
}
于 2013-11-11T12:55:02.313 に答える