0

lucene インデックスで検索を実行する複数のスレッドがあります。各検索の前に、コンテンツが既にインデックス化されているかどうかがチェックされ、インデックス化されていない場合はインデックスに追加されます。インデックスが作成されていないコンテンツに対して 2 つの並列検索が同時に発生すると、ドキュメントが重複し、検索結果がめちゃくちゃになると推測されます。

次のメソッドを見つけました: IndexWriter.updateDocument

しかし、これは私が直面しているマルチスレッドの問題を解決しないと思います。

これを解決する方法についての提案は大歓迎です。

4

2 に答える 2

1

最初に、一度に 1 つの method( IndexWriter#updateDocument()) 呼び出しのみがあることを確認します。次のように、スレッドに属する共有オブジェクトでそれを実現します。

class Search implements Runnable{
private Object lock=new Object();
private volatile boolean found=false;
    public void run(){
      //business
      if(<<found something!>> && !found){
        synchronized(lock){/*call the related-method*/found=true;}
      }
      //business
      }
}

次に、重複を避けるために検索中に見つかったすべてのキーを追跡する必要があります。おそらくキーをチェックするか、単純なブールチェックを使用します。

また、検索のためにプロセスを中止することについて別のスレッドに通知することにより、無駄なプロセスに注意してください。最初に作成されたキーだけが必要な場合は、ビジネスに依存します。

于 2013-10-04T19:53:45.127 に答える
0

更新/追加のソースを変更して重複を避けることができない場合は、どこかにチョーク ポイントを作成する必要があります。目標は、可能な限り競合を最小限に抑えることです。

これを行う 1 つの方法は、要求キュー、作業キュー、およびルックアップ用の ConcurrentHashMap を用意することです。すべての新しいリクエストは、単一の「ゲートキーパー」スレッドによって処理されるリクエスト キューに追加されます。ゲートキーパーは、一度に 1 つの要求を取得するか、キューを空にして保留中のすべての要求をループで処理し、その側での競合を減らすことができます。

リクエストを処理するために、ゲートキーパーは ConcurrentHashMap で putIfAbsent を実行します。戻り値が null の場合、更新/挿入要求を実際の作業キューに追加できます。値がすでにマップにある場合は....以下の #2 を参照してください。putIfAbsent はアトミックであるため、現実的には複数のゲートキーパーを使用できますが、HashMap での競合が増えるだけです。ゲートキーパーの実際の処理時間は非常に短いため、リクエスト キューにそれらを追加しても、実際には何も得られません。

ワーク キュー スレッドは、同じレコードを変更しない限り、複数の更新/挿入を同時に処理できます。ワーク キュー スレッドが要求の処理を終了すると、ConcurrentHashMap から値を削除して、ゲートキーパーがそのレコードを再度変更しても安全であることを認識できるようにします。

--

考慮すべき点:

1) 同時にできることをどのように定義しますか? 2 つの異なるリクエストが同じドキュメントを同時に変更することは望ましくないため、リクエスト全体をハッシュするべきではないでしょう。

2) すでにキューに重複があるために現在処理できないリクエスト (またはポイント 1 のように同じドキュメントを変更するリクエスト) はどうしますか? それらを捨てる?それらを定期的に再試行する二次更新キューに入れますか? 元のリクエスタのリクエストが無期限保留パターンの場合、どのように対応しますか?

3) リクエストが処理される順序は重要ですか?

于 2013-10-04T23:29:27.803 に答える