Lucene多线程操作实现
对于并发,Lucene 遵循以下规则:
1. 允许任意多的读操作并发,即任意数量用户可同时对同一索引做检索操作。
2. 即便正在进行索引修改操作(索引优化、添加文档、删除文档),依然允许任意多的检索操作并发执行。
3. 不允许并发修改操作,也就是说同一时间只允许一个索引修改操作。
Lucene内部已经对多线程安全进行了处理,很多操作都使用了 lock 进行多线程同步锁定。只要遵循一定的规则,就可以在多线程环境下安全运行 Lucene。
方案一:
建议:
1. Directotry、Analyzer 都是多线程安全类型,只需建立一个 Singleton 对象即可。
2. 所有线程使用同一个 IndexModifier 对象进行索引修改操作。
3. IndexWriter/IndexReader/IndexModifier/IndexSearcher 最好使用同一个 Directory 对象,否则多线程并发读写时可能引发 FileNotFoundException。
IndexModifier 对象封装了 IndexWriter 和 IndexReader 的常用操作,其内部实现了多线程同步锁定。使用 IndexModifier 可避免同时使用 IndexWriter 和 IndexReader 时需要在多个对象之间进行同步的麻烦。等所有修改操作完成后,记住调用 Close() 方法关闭相关资源。并不是每次操作都需要调用 Optimize(),可以依据特定情况,定期执行优化操作。
--------
以下演示代码简单封装了一个 IndexModifier Signleton 类型,确保多线程使用同一个对象,且只能由最后一个多线程调用 Close 方法关闭。
代码不完善,仅供参考!需要做些修改才能应用于实际项目。
//索引修改器的获取和关闭
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexModifier;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
public class MyIndexModifier {
private static Analyzer analyzer = new StandardAnalyzer();
private static IndexModifier modifier;
private static ArrayList<Thread> threadList = new ArrayList<Thread>();
private MyIndexModifier() { }
static final File INDEX_DIR = new File("D:/docindex");
public static IndexModifier GetInstance()
{
synchronized (threadList)
{
if (modifier == null)
{
try {
modifier = new IndexModifier(INDEX_DIR, analyzer, false);
//索引性能测试参数配置
modifier.setMergeFactor(1000);
System.out.println("MergeFactor: " + modifier.getMergeFactor());
System.out.println("MaxBufferedDocs: " + modifier.getMaxBufferedDocs());
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if (!threadList.contains(Thread.currentThread()))
threadList.add(Thread.currentThread());
return modifier;
}
}
public static void Close()
{
synchronized (threadList)
{
if (threadList.contains(Thread.currentThread()))
threadList.remove(Thread.currentThread());
if (threadList.size() == 0)
{
try {
if (modifier != null)
{
modifier.close();
modifier = null;
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}