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