06月12, 2014

Lucene的IndexWriter在初始化的时候遇到IndexWriter is closed的问题

Lucene3.5之后,IndexWriter的初始化有了一个IndexConfig来作为其初始化的参数,当我们在使用IndexWrier的时候一定要注意在最后把writer关闭,下面是我在平时的使用中遇到的问题:

1、初始化IndexWriter遇到的异常:

org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@D:\lucenespace\baidu\write.lock at org.apache.lucene.store.Lock.obtain(Lock.java:84) at org.apache.lucene.index.IndexWriter.(IndexWriter.java:1108)

其实这个异常是因为lucene进入到索引目录中,发现里面就是一个write.lock。而IndexWriter的构造函数在试图获取另外一个IndexWriter已经加锁的索引目录时就会抛出一个LockObtainFailedException。

当IndexWriter在初始化索引的时候会为这个索引加锁,等到初始化完成之后会调用其close()方法关闭IndexWriter,在close()这个方法的内部其实也是调用了unlock()来释放锁,当程序结束后IndexWriter没有正常关闭的时候

这个锁也就没有被释放,等待下次对同样的索引文件创建IndexWriter的时候就会抛出该异常,所以在对某一个已经创建过索引的文件初始化IndexWriter的时候可以使用下面的方法检查一下:

if(IndexWriter.isLocked(dir)) IndexWriter.unlock(dir);

网上说是这样可以,但是我在加了这句代码之后又抛出了个异常:

org.apache.lucene.store.LockReleaseFailedException: Cannot forcefully unlock a NativeFSLock which is held by another indexer component: D:\lucenespace\baidu\write.lock at org.apache.lucene.store.NativeFSLock.release(NativeFSLockFactory.java:294) at org.apache.lucene.index.IndexWriter.unlock(IndexWriter.java:4654)

程序还是没法释放掉之前的writer加的锁,所以我的解决办法是直接从这个索引文件里删除掉write.lock这个文件,不过只要你的java虚拟机一直在运行的话这个是删除不掉的,会有这个提示:

我的做法是在进程管理里面杀掉javaw.exe之后才删除了,然后把writer.lock这个文件删除之后IndexWriter就可以初始化成功了

2、接下来就是把程序中代码改了,每一次的IndexWriter都要进行关闭,还有一个建议,每次在IndexWriter发生异常的时候进行unlock一下,这样也是可以的,不过最好还是不要忘记关闭。

如果整个程序中只有一个writer的话是没有问题,但是同时有多个IndexWriter在运行的时候就会出现org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@E:\indexDir\write.lock的异常,所以对于同一个索引库,只能有一个打开IndexWtriter操作,如果打开了多个,就会有上面的异常。

3、最后的总结就是

a. 在每次初始化IndexWriter的时候都要检查一下看该索引有没有被加锁

if(IndexWriter.isLocked(dir))

IndexWriter.unlock(dir);

b.  在创建索引的时候如果发生异常,一定要IndexWriter.unlock(dir)或者 writer.rollback()也是可以的

c.  在使用完之后一定要记得close()关闭索引

以上是我在做程序的时候的一些总结,大家如果觉得有什么不完善或者需要改动麻烦告诉我,我随时改正,谢谢。

本文链接:http://blogs.360.cn/post/lucene的indexwriter在初始化的时候遇到indexwriter-is-closed的问题.html

-- EOF --

Comments