作者: 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推荐




文章来源:http://yagesi.javaeye.com/blog/165604
posted on 2008-07-05 12:20  Zen.赱L  阅读(726)  评论(0编辑  收藏  举报