3

我的问题很简单,当使用IndexReader.openIfChanged (reader)replace之前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
}

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

IndexReaderinstance( readerobject) 是全局唯一的

由于这个变化,我得到一个例外:

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对象)

在此处输入图像描述

我需要关闭oldReader只是因为:

参考:

我该如何解决这个问题?

4

5 回答 5

5

查看 NRTManager 和 SearcherManager。你真的不必自己处理这个。

于 2012-07-09T03:41:36.057 回答
3

您需要在对var 的写入与从其他线程对它们的后续读取happens-before之间施加关系。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 中。查看NRTManagerReopenThread 上的 Javadoc以获取您需要的所有信息,包括完整的代码示例。

于 2012-07-09T07:54:45.727 回答
0

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

reader.decRef()当引用数为 0 时自动关闭阅读器。

于 2012-07-09T03:07:37.730 回答
0

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

于 2012-07-08T12:05:47.577 回答
0

我根本看不到 oldReader 和 oldSearcher 在做什么!!!!难道你不能把它们连同它们一起删除吗?close() 如果你仍然需要它们,那么我敢打赌,oldSearcher 在某种程度上与 oldReader 相关,所以调用close()oldSearcher 也会导致关闭 oldReader 这就是你得到异常的原因是整个代码量,还是你简化了它?如果是,则首先删除 oldReader 和 oldSearcher

干杯

于 2012-07-08T12:07:08.403 回答