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.<init>(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()关闭索引
以上是我在做程序的时候的一些总结,大家如果觉得有什么不完善或者需要改动麻烦告诉我,我随时改正,谢谢。