上下文:
帮助器外观类为我的应用程序提供搜索方法。
由于性能不是问题,因此会为每个查询创建一个新的IndexSearcher
。
对于每个查询,都会创建一个新的搜索器:
File indexFile = new File(String absolutePathToIndex);
IndexSearcher searcher = new IndexSearcher(indexFile.getAbsolutePath(), true);
有时我会得到AlreadyClosedException
我不理解的内容,因为没有共享搜索者对象。
有什么想法吗?有关如何打开索引的最佳做法?已知的问题? 感谢。
堆栈跟踪:
org.apache.lucene.store.AlreadyClosedException: this Directory is closed
at org.apache.lucene.store.Directory.ensureOpen(Directory.java:251)
at org.apache.lucene.store.FSDirectory.listAll(FSDirectory.java:530)
at org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java:585)
at org.apache.lucene.index.DirectoryReader.open(DirectoryReader.java:69)
at org.apache.lucene.index.IndexReader.open(IndexReader.java:476)
at org.apache.lucene.index.IndexReader.open(IndexReader.java:243)
at org.apache.lucene.search.IndexSearcher.<init>(IndexSearcher.java:78)
建议的解决方案#1:要走的路?
Directory directory = FSDirectory.open(File indexFile);
IndexSearcher searcher = new IndexSearcher(directory, true);
...do the query...
searcher.close();
问题:为EACH查询创建解决方案#1的上述代码。是否有必要关闭目录?检查Lucene 2.9.2的源代码后,searcher.close()
不会关闭与内部directory
对象关联的reader
。
答案 0 :(得分:1)
您在此示例中调用的方法无论如何都是不推荐使用的。因此,使用IndexSearcher(Directory path, boolean readOnly)
可能会显示不同的行为。
您需要确保在每次后续搜索完成之前不要关闭目录。因此,例如,如果您多次使用此目录并重新安排搜索器,则其他搜索器将被销毁,并可能在析构函数中关闭目录。
因此,如果您已使用已弃用的ctor版本,请尝试为每个Searcher使用新的Directory实例。
答案 1 :(得分:1)
对于较新版本的Lucene,我建议使用SearcherManager
帮助程序类,它最终隐藏了您必须自己实现的所有并发/锁定和生命周期步骤。
来自Mike McCandless的基本教程,一个Lucene项目的新手:http://blog.mikemccandless.com/2011/09/lucenes-searchermanager-simplifies.html
答案 2 :(得分:0)
如果错误仅在高并发加载下发生,则表明您可能有多个线程尝试关闭目录或尝试从已关闭的目录中读取。您还没有弄清楚absolutePath
是方法中的局部变量,还是被多个重用的对象中的实例变量
线程 - 因此很难猜测。