如何安全地关闭IndexReader?

时间:2012-07-08 11:57:52

标签: java lucene

我的问题很简单,当使用IndexReader.openIfChanged (reader)替换之前的reader时,如何安全关闭oldReader

以下是代码:(使用Lucene 3.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
}

这个代码在deamon线程中,每5秒运行一次

IndexReader instance(reader object)是全局唯一的

由于此更改,我得到一个例外:

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:392使用reader对象(IndexReader实例,全球唯一)

IndexManager.query方法有大量并发请求,所有请求都使用全局唯一IndexReader实例(reader对象)

enter image description here

我需要关闭oldReader只是因为:

参考:

如何解决这个问题?

5 个答案:

答案 0 :(得分:5)

查看NRTManager和SearcherManager。你真的不需要自己处理。

答案 1 :(得分:3)

您需要在happens-before vars的写入与其他线程的后续读取之间建立public static关系。如果你使用多个var,你就会遇到原子性问题所以我建议你只使用一个var,因为这就是你所需要的。

简单地说,这对您有用:

public class SearcherManager 
{
  public static volatile IndexSearcher searcher;

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

关键是volatile修饰符。确保在写入var之前完全初始化所有内容,但在写入之后关闭旧对象,换句话说,请确保按照现在的方式继续执行:)

但是,正如@MJB在他的回答中指出的那样,你应该真的不要这样做,因为它全都内置在Lucene中。查看Javadoc on NRTManagerReopenThread以获取所需的所有信息,包括完整的代码示例。

答案 2 :(得分:0)

我假设搜索者(后来被称为oldSearcher)在读取器(oldReader)上工作,在这种情况下,当你关闭它时,它也关闭它所使用的阅读器,所以你不需要关闭它, oldSearcher.close()就足够了。

答案 3 :(得分:0)

我根本看不到oldReader和oldSearcher在做什么!!!!! 您不能将它们与close()一起删除 如果你仍然需要它们,那么我的赌注是oldSearcher以某种方式与oldReader相关,因此在oldSearcher上调用close()也会导致关闭oldReader,这就是你获得异常的原因 这是整个代码的大小,还是简化了它?如果是第一个,那么只需删除oldReader和oldSearcher

干杯

答案 4 :(得分:0)

看一下indexreader引用计数方法。 即,在使用实例化新的IndexSearcher时增加引用计数 reader.incRef();并在完成搜索结果后减少它,最好在reader.decRef()的try catch方法的finally语句中减少;

当引用数为0时,

reader.decRef()会自动关闭阅读器。