Lucene6入门教程(七)多目录多线程索引/检索

释放双眼,带上耳机,听听看~!

在使用lucene6 的时候,会遇到多目录多线程的索引构建和检索(查询)情况。


把不同类型的数据放到同一个索引文件中,这是不现实的,而且,除了内存索引,创建多目录索引也能提高索引速度,这是因为,一个索引目录只能有一把锁,那如果有多个索引目录,每个索引目录发一把锁,N个索引目录同时进行索引写操作就有意义了。


而检索的时候,也需要多线程并发来提高搜索速度。


以上,就可以用到多目录多线程问题了,本文主要参考solarrrr的博客文,
地址为:[http://blog.csdn.net/asdfsadfasdfsa/article/details/77649108]
全部建好类,才好操作的


下边是代码,首先是LuceneUtils工具类,封装各个对象,是为防止Index和Search过程时候的读冲突或写冲突等做准备的。

然后是一个LuceneManager类

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
/**
* Lucene索引读写器/查询器单例获取工具类
* @author Lanxiaowei
*
*/
public class LuceneManager {
private volatile static LuceneManager singleton; private volatile static IndexWriter writer; private volatile static IndexReader reader;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
1private volatile static IndexSearcher searcher;
2
3private final Lock writerLock = new ReentrantLock();
4
5//private final Lock readerLock = new ReentrantLock();
6
7//private final Lock searcherLock = new ReentrantLock();
8
9
10private static ThreadLocal<IndexWriter> writerLocal = new ThreadLocal<IndexWriter>();
11
12private LuceneManager() {}
13
14public static LuceneManager getInstance() {
15    if (null == singleton) {
16        synchronized (LuceneManager.class) {
17            if (null == singleton) {
18                singleton = new LuceneManager();
19            }
20        }
21    }
22    return singleton;
23}
24
25/**
26 * 获取IndexWriter单例对象
27 * @param dir
28 * @param config
29 * @return
30 */
31public IndexWriter getIndexWriter(Directory dir, IndexWriterConfig config) {
32    if(null == dir) {
33        throw new IllegalArgumentException("Directory can not be null.");
34    }
35    if(null == config) {
36        throw new IllegalArgumentException("IndexWriterConfig can not be null.");
37    }
38    try {
39        writerLock.lock();
40        writer = writerLocal.get();
41        if(null != writer) {
42            return writer;
43        }
44        if(null == writer){            //如果索引目录被锁,则直接抛异常
45            if(IndexWriter.isLocked(dir)) {
46                throw new LockObtainFailedException("Directory of index had been locked.");
47            }
48            writer = new IndexWriter(dir, config);
49            writerLocal.set(writer);
50        }
51    } catch (LockObtainFailedException e) {
52        e.printStackTrace();
53    } catch (IOException e) {
54        e.printStackTrace();
55    } finally {
56        writerLock.unlock();
57    }
58    return writer;
59}
60
61/**
62 * 获取IndexWriter[可能为Null]
63 * @return
64 */
65public IndexWriter getIndexWriter() {
66    return writer;
67}
68
69/**
70 * 获取IndexReader对象
71 * @param dir
72 * @param enableNRTReader  是否开启NRTReader
73 * @return
74 */
75public IndexReader getIndexReader(Directory dir,boolean enableNRTReader) {
76    if(null == dir) {
77        throw new IllegalArgumentException("Directory can not be null.");
78    }
79    try {
80        if(null == reader){
81            reader = DirectoryReader.open(dir);
82        } else {
83            if(enableNRTReader && reader instanceof DirectoryReader) {
84                //开启近实时Reader,能立即看到动态添加/删除的索引变化
85                reader = DirectoryReader.openIfChanged((DirectoryReader)reader);
86            }
87        }
88    } catch (IOException e) {
89        e.printStackTrace();
90    }
91    return reader;
92}
93
94/**
95 * 获取IndexReader对象(默认不启用NETReader)
96 * @param dir
97 * @return
98 */
99public IndexReader getIndexReader(Directory dir) {
100    return getIndexReader(dir, false);
101}
102
103/**
104 * 获取IndexSearcher对象
105 * @param reader    IndexReader对象实例
106 * @param executor  如果你需要开启多线程查询,请提供ExecutorService对象参数
107 * @return
108 */
109public IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) {
110    if(null == reader) {
111        throw new IllegalArgumentException("The indexReader can not be null.");
112    }
113    if(null == searcher){
114        searcher = new IndexSearcher(reader);
115    }
116    return searcher;
117}
118
119/**
120 * 获取IndexSearcher对象(不支持多线程查询)
121 * @param reader    IndexReader对象实例
122 * @return
123 */
124public IndexSearcher getIndexSearcher(IndexReader reader) {
125    return getIndexSearcher(reader, null);
126}
127
128/**
129 * 关闭IndexWriter
130 * @param writer
131 */
132public void closeIndexWriter(IndexWriter writer) {
133    if(null != writer) {
134        try {
135            writer.close();
136            writer = null;
137            writerLocal.remove();
138        } catch (IOException e) {
139            e.printStackTrace();
140        }
141    }
142}
143

}
多线程索引的类IndexCreator,防止写冲突等

接着便是分页的类

还有一个分页查询的类

这里是高亮查询

接着,
最后,就是测试了,先建立索引,然后各种测试
Index测试

Search测试

还有一个索引文档,索引目录地址这些,需要你自己去改改
参考文献:
lucene5版索引创建:http://blog.csdn.net/asdfsadfasdfsa/article/details/77649108
多线程多目录索引:http://blog.csdn.net/asdfsadfasdfsa/article/details/77649363
多线程并发问题:http://www.voidcn.com/article/p-oiioiwog-do.html
注意:http://www.voidcn.com/article/p-uvbqnurg-mw.html

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索