Lucene之IndexWriter、IndexReader保证唯一实例(备忘)

大家知道,lucene中的IndexWriter和IndexReader都是线程安全的类,但是不能出现多多线程绑定多个实例的情况。因此很有必要保证IndexWriter和IndexReader全局只有一个实例子。我们首先写一个类,让他来保证全局只有一个实例,类的接口如下:

1 public interface LuceneManager {
2      public IndexWriter getIndexWriter() throws CorruptIndexException, LockObtainFailedException, IOException;
3      public IndexReader getIndexReader() throws CorruptIndexException, IOException;
4      public void  closeIndexWriter() throws IOException;
5      public  void closeIndexReader() throws IOException;
6      public  void closeAll() throws IOException;
7 }

接口实现类代码如下,主要看看它如何保证只有一个实例:

 1 package com.geostar.poi.support.lucene;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 
 6 import org.apache.log4j.Logger;
 7 import org.apache.lucene.analysis.Analyzer;
 8 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 9 import org.apache.lucene.index.CorruptIndexException;
10 import org.apache.lucene.index.IndexReader;
11 import org.apache.lucene.index.IndexWriter;
12 import org.apache.lucene.index.IndexWriter.MaxFieldLength;
13 import org.apache.lucene.store.FSDirectory;
14 import org.apache.lucene.store.LockObtainFailedException;
15 import org.apache.lucene.util.Version;
16 
17 import com.geostar.poi.support.POIConfig;
18 
19 public class POILuceneManager implements LuceneManager{
20     private IndexWriter  indexWriter=null;
21     private IndexReader  indexReader=null;
22     //------lock 1
23     private Object lock_w=new Object();
24     //------lock 2
25     private Object lock_r=new Object();
26     
27     private Logger logger=Logger.getLogger(POILuceneManager.class);
28     @Override
29     public IndexWriter getIndexWriter() throws CorruptIndexException, LockObtainFailedException, IOException {        
30         synchronized(lock_w){
31            if(indexWriter==null){
32              System.out.println("创建对象");
33              if(IndexWriter.isLocked(FSDirectory.open(new File(POIConfig.DEFULT_POI_LUCENNE_INDEX_PATH)))){
34                  IndexWriter.unlock(FSDirectory.open(new File(POIConfig.DEFULT_POI_LUCENNE_INDEX_PATH)));
35              };
36              Analyzer any=new StandardAnalyzer(Version.LUCENE_CURRENT);
37              indexWriter=new IndexWriter(FSDirectory.open(new File(POIConfig.DEFULT_POI_LUCENNE_INDEX_PATH)),any,MaxFieldLength.UNLIMITED );
38            };
39            
40        }
41         return indexWriter;
42     }
43 
44     @Override
45     public IndexReader getIndexReader() throws CorruptIndexException, IOException {
46       synchronized (lock_r) {
47             if(indexReader==null){
48                 indexReader=IndexReader.open(FSDirectory.open(new File(POIConfig.DEFULT_POI_LUCENNE_INDEX_PATH)));
49             };
50         }
51         return  indexReader;
52     }
53 
54     @Override
55     public void closeIndexWriter() throws IOException {
56         // TODO Auto-generated method stub
57 //synchronized (lock_w) {
58             if(this.indexWriter!=null){
59                 this.indexWriter.close();
60             };
61         //}
62         
63     }
64 
65     @Override
66     public void closeIndexReader() throws IOException {
67         // TODO Auto-generated method stub
68 //synchronized (lock_r) {
69             if(this.indexReader!=null){
70                 this.indexReader.close();
71             };
72         //}
73         
74         
75     }
76 
77     @Override
78     public void closeAll() throws IOException {
79         // TODO Auto-generated method stub
80         this.closeIndexReader();
81         this.closeIndexWriter();
82         
83     }
84 
85 }

其中的synchronized代码块很重要,它保证只能创造一个IndexWriter实例。为了测试它能不能达到我们要的结果,我来写一个测试类。

测试类代码如下:

 1 package com.geostar.poi.support;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.lucene.index.CorruptIndexException;
 6 import org.apache.lucene.index.IndexWriter;
 7 import org.apache.lucene.store.LockObtainFailedException;
 8 
 9 import com.geostar.poi.support.lucene.LuceneManager;
10 import com.geostar.poi.support.lucene.POILuceneManager;
11 
12 public class LuceneThreadTest {
13 
14     /**
15      * @param args
16 */
17     public static void main(String[] args) {
18         final LuceneManager manager=new POILuceneManager();
19             for(int i=0;i<100;i++){
20                 new Thread(new Runnable() {
21                     
22                     @Override
23                     public void run() {
24                         try {
25                             Thread.currentThread().sleep(500);
26                         } catch (InterruptedException e) {
27                             // TODO Auto-generated catch block
28                             e.printStackTrace();
29                         }
30 
31                         
32                         try {
33                             IndexWriter writer=manager.getIndexWriter();
34                         } catch (CorruptIndexException e) {
35                             // TODO Auto-generated catch block
36                             e.printStackTrace();
37                         } catch (LockObtainFailedException e) {
38                             // TODO Auto-generated catch block
39                             e.printStackTrace();
40                         } catch (IOException e) {
41                             // TODO Auto-generated catch block
42                             e.printStackTrace();
43                         }finally{
44                             try {
45                                 manager.closeAll();
46                             } catch (IOException e) {
47                                 // TODO Auto-generated catch block
48                                 e.printStackTrace();
49                             }
50                         }
51                         
52                     }
53                 }).start();
54             };
55     }
56 
57 }

ok ,运行代码,只见后台出现以下信息:

log4j:WARN No such property [maxBackupIndex] in org.apache.log4j.DailyRollingFileAppender.
log4j:WARN No such property [maxFileSize] in org.apache.log4j.DailyRollingFileAppender.
创建对象

看来这个结果还是比较正常,每个线程中执行getIndexWriter方法,获得对象之后,然后关闭对象,关闭文件锁。那么我们将PoiLuceneManager中synchronized代码块注释掉,再看看效果如何,控制台信息如下:

log4j:WARN No such property [maxBackupIndex] in org.apache.log4j.DailyRollingFileAppender.
log4j:WARN No such property [maxFileSize] in org.apache.log4j.DailyRollingFileAppender.
创建对象
创建对象
创建对象
创建对象
创建对象
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@C:\CommonServices\poi\write.lock
	at org.apache.lucene.store.Lock.obtain(Lock.java:84)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1041)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1016)
	at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:887)
	at com.geostar.poi.support.lucene.POILuceneManager.getIndexWriter(POILuceneManager.java:37)
	at com.geostar.poi.support.LuceneThreadTest$1.run(LuceneThreadTest.java:33)
	at java.lang.Thread.run(Thread.java:619)
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@C:\CommonServices\poi\write.lock
	at org.apache.lucene.store.Lock.obtain(Lock.java:84)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1041)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1016)
	at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:887)
	at com.geostar.poi.support.lucene.POILuceneManager.getIndexWriter(POILuceneManager.java:37)
	at com.geostar.poi.support.LuceneThreadTest$1.run(LuceneThreadTest.java:33)
	at java.lang.Thread.run(Thread.java:619)
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@C:\CommonServices\poi\write.lock
	at org.apache.lucene.store.Lock.obtain(Lock.java:84)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1041)
	at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1016)
	at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:887)
	at com.geostar.poi.support.lucene.POILuceneManager.getIndexWriter(POILuceneManager.java:37)
	at com.geostar.poi.support.LuceneThreadTest$1.run(LuceneThreadTest.java:33)
	at java.lang.Thread.run(Thread.java:619)

 但看打印多个“创建对象”已经知道此方法无法保证只能创建一个IndexWriter对象,同时错误信息也表示多个对象锁冲突,并发出现问题。

综上,IndexWriter是线程安全对象,但是不容许多线程操作多个IndexWriter实例对象,IndexReader亦然。当然也要记住LuceneManager对象也要单例喔,不然上面代码也全部作废,达不到预想效果,不信你可以试试。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值