我的问题很简单,当使用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
对象)
我需要关闭oldReader
只是因为:
参考:
如何解决这个问题?
答案 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语句中减少;
reader.decRef()
会自动关闭阅读器。