关于lucene的IndexSearcher是否单实例

来源:互联网 发布:如何评价哈利波特知乎 编辑:程序博客网 时间:2024/05/18 06:27

转载:http://www.2016k.com/programmer/java/06-40.html

转载:http://www.cnblogs.com/huangfox/archive/2010/10/14/1851233.html

参考:http://lucene-group.group.iteye.com/group/topic/24404

将indexReader和IndexSearcher的实例在搜索方法中创建,为了节约系统开销、提高效率,

应该将这些实例作为单例模式。

在创建indexSearcher时,程序是把索引文件全部载入内存,这样一来,你查询一次,他载一次,,会致使内存不足,,所以你需要的是,,对一个索引文件夹下的文件只创建一次indexSarcher

一般情况下,lucene的IndexSearcher都要写成单实例,因为每次创建IndexSearcher对象的时候,它都需要把索引文件加载进来,如果访问量比较大,而索引也比较大,那就很容易造成内存溢出!

但是如果仅仅按照一般的单实例来写的话,如果更新了索引,那么在不重启服务的情况下,Searcher对象是搜索不到索引更新后的内容的.如何解决呢,这里给出一个方法!

在这个方法里,建造了一个Factory类,分别管理IndexReader和IndexSearcher的单实例.

import java.io.File; import java.io.IOException; import java.util.Date; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.store.SimpleFSDirectory; /** * 工厂类,负责管理IndexReader、IndexSearcher * @author .K' */ public class LuceneFactory {private static IndexReader reader = null;private static IndexSearcher searcher = null; /** *获得IndexReader对象,判断是否为最新,不是则重新打开 (以下省略了try...catch) *@param  file    索引路径的File对象 *@return   IndexReader对象 **/ public static synchronized IndexReader getIndexReader(File file){ if (reader == null) { reader = IndexReader.open(SimpleFSDirectory.open(file)); } else { if(!reader.isCurrent()){ reader = reader.reopen(); } } return reader; } /** * 获得IndexSearcher对象,判断当前的Searcher中reader是否为最新,如果不是,则重新创建IndexSearcher(省略了try...catch) * @param reader *            IndexReader对象 * @return IndexSearcher对象 */ public static synchronized IndexSearcher getIndexSearcher(IndexReader reader) { if (searcher == null) { searcher = new IndexSearcher(reader); }else{ IndexReader r = searcher.getIndexReader(); if(!r.isCurrent()){ searcher = new IndexSearcher(reader); } } return searcher; } }

调用工厂类中的方法创建Searcher

IndexReader reader = LuceneFactory.getIndexReader(new File(path)); Searcher searcher = LuceneFactory.getIndexSearcher(reader);

以上就可以解决对于索引无法实时搜索的问题了!


IndexSearcher初始化,IndexSearcher(Directory dir)和IndexSearcher(IndexReader reader)有什么区别?到底使用那个更合理?

IndexSearcher的构造方法如下:

Constructor SummaryIndexSearcher(Directory path)
          Creates a searcher searching the index in the named directory, with readOnly=trueIndexSearcher(Directory path, boolean readOnly)
          Creates a searcher searching the index in the named directory.IndexSearcher(IndexReader r)
          Creates a searcher searching the provided index.IndexSearcher(IndexReader reader, IndexReader[] subReaders, int[] docStarts)
          Expert: directly specify the reader, subReaders and their docID starts.

其中指定到索引给出了两种方式:

1.给出索引的Directory;

2.给出索引的IndexReader;

从源代码可知:

public IndexSearcher(Directory path) throws CorruptIndexException, IOException {    this(IndexReader.open(path, true), true);  }  public IndexSearcher(Directory path, boolean readOnly) throws CorruptIndexException, IOException {    this(IndexReader.open(path, readOnly), true);  }  public IndexSearcher(IndexReader r) {    this(r, false);  }

直接给出Directory的构造方式其实也是打开了一个IndexReader,不过在调用方法

IndexSearcher(IndexReader r, boolean closeReader)

时给出的第二个参数(closeReader)为true,而直接给出IndexReader实例的构造方法给出的closeReader参数为false。

那么这个参数到底起到什么作用呢?

我们来看看IndexSearcher的Close方法的源码:

public void close() throws IOException {    if(closeReader)      reader.close();  }

原来使用Directory的构造方法在执行IndexSearcher的close方法后会将IndexReader关闭,

而是用IndexReader实例的构造方法在执行close方法后不会讲IndexReader实例关闭。

可以理解为IndexReader实例和IndexSearcher实例是分离的。

可以这么说?两种方式的区别就是IndexSearcher实例close后给出的IndexReader实例是否关闭!

那么在实际应用中,应该是用那种方式呢?

从源码中可以看出,使用Directory构造的IndexSearcher实例各自持有一个IndexReader实例,若系统中存在多个IndexSearcher实例时,将影响系统的性能(占用过多的内存空间)。

理想的做法应该是一份索引用一个IndexReader实例打开,IndexSearcher实例是用IndexReader进行构造。


原创粉丝点击