• 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对象也要单例喔,不然上面代码也全部作废,达不到预想效果,不信你可以试试。



     

  • 相关阅读:
    git merge
    google platform
    http tutorial
    DS,AA tree
    Java,Hashtable
    java,Object
    Pumping lemma for regular languages
    Pumping lemma
    Context-free grammar
    Formal language
  • 原文地址:https://www.cnblogs.com/likehua/p/2359087.html
Copyright © 2020-2023  润新知