您的位置:首页 > 其它

[导入]Lucene并发访问

2008-07-05 12:20 148 查看
作者: yagesi
链接:http://yagesi.javaeye.com/blog/165604
发表时间: 2008年02月27日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

在Lucene并发访问中,如果出现线程冲突,会造成索引文件的损坏,系统出现Lock obtain timed Out异常. 索引文件的临时目录会多一个work.lock或者commit.lock的文件,证明你并发访问出现了问题,索引文件已经损坏...

在Lucene in Action中给出IndexWriter和IndexReader并发访问操作矩阵,矩阵中描述了两个操作不能同时执行的描述:

矩阵可以归纳为:

IndexReader对象在从索引中删除一个文档时,IndexWriter对象不能向该索引库添加文档
IndexWriter对象在索引进行优化时,IndexReader对象不能从其中删除文档
IndexWriter对象在对索引进行合并时,IndexReader对象也不能从其中删除文档
以上三点引自 Lucene in Action 第二章

其实在程序中,到底该索引是否被锁定,我们可以通过IndexReader类的静态方法isLocked(Directory)进行判定..我测试过,如果使用IndexWriter访问索引,那么在我们创建IndexWriter对象的时候,索引文件就会被锁定,当调用IndexWriter的close方法时,锁才释放...当我们使用IndexReader访问索引文件时,当我们使用open打开索引时,文件不会被锁定,只有执行deleteDocument方法时才锁定,IndexReader的close方法时才释放...

所以在并发访问索引文件的时候,我们除了要保证IndexWriter和IndexReader它们各自的并发访问的线程安全外,还要保证IndexWriter和IndexReader之间的并发访问...

下面是我实现的部分代码:

public class IndexManager {
private static Analyzer analyzer = null;

private static IndexWriter _company_writer = null;

private static IndexReader _company_reader = null;

private static List<Thread> _company_writer_thread = new ArrayList();

private static List<Thread> _company_reader_thread = new ArrayList();

static{
Paoding paoding = PaodingMaker.make();
analyzer =  PaodingAnalyzer.writerMode(paoding);
}
private IndexManager(){}

public static IndexWriter getCompanyIndexWriter(String path,Boolean isReBuild){
synchronized(_company_writer_thread){
if(_company_writer==null){
try {
while(true){
if(!IndexReader.isLocked(path)){
_company_writer = new IndexWriter(path,analyzer,isReBuild);
break;
}else{
try {
Thread.sleep(100);
Thread.yield();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if(!_company_writer_thread.contains(Thread.currentThread()))_company_writer_thread.add(Thread.currentThread());
return _company_writer;
}
}

public static void closeCompanyIndexWriter(){
synchronized(_company_writer_thread){
if (_company_writer_thread.contains(Thread.currentThread()))
_company_writer_thread.remove(Thread.currentThread());

if (_company_writer_thread.size() == 0)
{
if (_company_writer != null)
{
try {
_company_writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
_company_writer = null;
}
}

}
}

public static IndexReader getCompanyIndexReader(String path){
synchronized(_company_reader_thread){
if(_company_reader==null){
try {
while(true){
if(!IndexReader.isLocked(path)){
_company_reader = IndexReader.open(path);
break;
}else{
try {
Thread.sleep(20);
Thread.yield();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if(!_company_reader_thread.contains(Thread.currentThread()))_company_reader_thread.add(Thread.currentThread());
return _company_reader;
}
}

public static void closeCompanyIndexReader(){
synchronized(_company_reader_thread){
if (_company_reader_thread.contains(Thread.currentThread()))
_company_reader_thread.remove(Thread.currentThread());

if (_company_reader_thread.size() == 0)
{
if (_company_reader != null)
{
try {
_company_reader.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
_company_reader = null;
}
}

}
}

}
[/code]

该类使用静态方法获取IndexWriter和IndexReader对象,在获取方法中,要判断该索引是否被锁定<IndexReader.isLocked(Directory)方法>,该方法主要为了防止IndexWriter和IndexReader它们之间的并发问题,至于IndexWriter和IndexReader它们自己本身的并发访问问题,使用了一个线程集合来进行管理,可以确保获取的访问对象不会出现同步问题.但是获取的IndexWriter或者IndexReader对象,在close的时候,一定要调用IndexManager的closeXXXXXXX()方法,这样线程池才能有效的管理IndexWriter,IndexReader实例线程...

Lucene并发访问问题就介绍到这里,由于刚刚开始学写帖子,有很多地方词不达意,表述不清,请大家谅解,我相信:会进步的...谢谢 

本文的讨论也很精彩,浏览讨论>>

JavaEye推荐

快来参加7月17日在成都举行的SOA中国技术论坛
JavaEye问答大赛开始了! 从6月23日 至 7月6日,奖品丰厚 !
北京: 千橡集团暨校内网诚聘软件研发工程师
Oracle专区上线,有Oracle最新文章,重要下载及知识库等精彩内容,欢迎访问。
搜狐网站诚聘Java、PHP和C++工程师

文章来源:http://yagesi.javaeye.com/blog/165604
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: