作者: 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;}}}}}
该类使用静态方法获取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