3

私の質問は非常に簡単です、使用するときIndexReader.openIfChanged (reader)は前のものを置き換えてくださいreader、安全に閉じる方法はoldReader

コードは次のとおりです:(Lucene3.5を使用)

IndexReader newReader=IndexReader.openIfChanged(reader);
if(newReader!=null){
    IndexReader oldReader=reader;
    IndexSearcher oldSearcher=searcher;

    reader=newReader;
    searcher=new IndexSearcher(newReader);

    oldSearcher.close();
    oldReader.close();//or oldReader.decRef(),result is the same
}

デーモンスレッドのこのコード、5秒ごとの実行時間

IndexReaderinstance(readerオブジェクト)はグローバルに一意です

この変更以降、例外が発生します。

org.apache.lucene.store.AlreadyClosedException: this IndexReader is closed
    at org.apache.lucene.index.IndexReader.ensureOpen(IndexReader.java:297)
    at org.apache.lucene.index.IndexReader.getSequentialSubReaders(IndexReader.java:1622)
    at org.apache.lucene.search.TermQuery$TermWeight.scorer(TermQuery.java:98)
    at org.apache.lucene.search.BooleanQuery$BooleanWeight.scorer(BooleanQuery.java:298)
    at org.apache.lucene.search.BooleanQuery$BooleanWeight.scorer(BooleanQuery.java:298)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:577)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:517)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:487)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:400)
    at org.zenofo.index.IndexManager.query(IndexManager.java:392)
    ...

IndexManager.java:392readerオブジェクトを使用する(IndexReaderインスタンス、グローバルに一意)

IndexManager.queryメソッドには多数の同時リクエストがあり、すべてのリクエストはグローバルに一意のIndexReaderインスタンス(readerオブジェクト)を使用します

ここに画像の説明を入力してください

oldReader次の理由だけで閉じる必要があります。

参照:

この問題を解決するにはどうすればよいですか?

4

5 に答える 5

5

NRTManagerとSearcherManagerを見てください。あなたは本当にこれを自分で処理する必要はありません。

于 2012-07-09T03:41:36.057 に答える
3

varsへの書き込みと、他のスレッドからのvarsの後続の読み取りとhappens-beforeの間に関係を課す必要があります。public static複数の変数を使用する場合、原子性の問題が発生するため、必要なのは1つの変数のみであるため、1つの変数のみを使用することをお勧めします。

簡単に言えば、これはあなたのために働くでしょう:

public class SearcherManager 
{
  public static volatile IndexSearcher searcher;

  private static void reopen() {
    // your code, just without assignment to reader
  }
}

キーはvolatile修飾子です。varに書き込む前にすべてを完全に初期化するようにしてください。ただし、書き込み後に古いオブジェクトを閉じてください。つまり、現在と同じように実行し続けるようにしてください:)

しかし、@ MJBが彼の回答で述べているように、これはすべてLuceneに組み込まれているため、実際にはこれを行うべきではありませんNRTManagerReopenThreadのJavadocをチェックして、完全なコードサンプルを含む必要なすべての情報を入手してください。

于 2012-07-09T07:54:45.727 に答える
0

oldReaderとoldSearcherが何をしているのかまったくわかりません!!!!! それらを一緒に削除することはできませんclose() まだそれらが必要な場合は、oldSearcherが何らかの形でoldReaderに関連しているため、oldSearcherを呼び出すとclose()、oldReaderも閉じます。これが、例外が発生する理由です。コードの大部分が、またはあなたはそれを単純化しましたか?最初に「はい」の場合は、oldReaderとoldSearcherを完全に削除します

乾杯

于 2012-07-08T12:07:08.403 に答える
0

リーダー(oldReader)で作業している場合、サーチャー(後でoldSearcherと呼ばれる)を想定します。その場合、サーチャーを閉じると、使用するリーダーも閉じるため、閉じる必要はありません。oldSearcher.close()は足りる。

于 2012-07-08T12:05:47.577 に答える
0

インデックスリーダーの参照カウント方法を見てください。つまり、で新しいIndexSearcherをインスタンス化するときに参照カウントを増やし、 reader.incRef();検索結果が終了したら、できれば;を使用してtrycatchメソッドのfinallyステートメントで参照カウントを減らしますreader.decRef()

reader.decRef()参照数が0の場合、リーダーを自動的に閉じます。

于 2012-07-09T03:07:37.730 に答える