Java 用lucene改进多线程索引
我正在尝试用多线程在Lucene中构建索引。因此,我开始编码并编写了以下代码。首先,我找到文件,并为每个文件创建一个线程对其进行索引。之后,我加入线程并优化索引。它是有效的,但我不确定。。。我能大规模信任它吗?有什么办法可以改进吗Java 用lucene改进多线程索引,java,multithreading,lucene,indexing,Java,Multithreading,Lucene,Indexing,我正在尝试用多线程在Lucene中构建索引。因此,我开始编码并编写了以下代码。首先,我找到文件,并为每个文件创建一个线程对其进行索引。之后,我加入线程并优化索引。它是有效的,但我不确定。。。我能大规模信任它吗?有什么办法可以改进吗 import java.io.File; import java.io.FileFilter; import java.io.FileReader; import java.io.IOException; import java.io.File; import jav
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Document;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.index.TermFreqVector;
public class mIndexer extends Thread {
private File ifile;
private static IndexWriter writer;
public mIndexer(File f) {
ifile = f.getAbsoluteFile();
}
public static void main(String args[]) throws Exception {
System.out.println("here...");
String indexDir;
String dataDir;
if (args.length != 2) {
dataDir = new String("/home/omid/Ranking/docs/");
indexDir = new String("/home/omid/Ranking/indexes/");
}
else {
dataDir = args[0];
indexDir = args[1];
}
long start = System.currentTimeMillis();
Directory dir = FSDirectory.open(new File(indexDir));
writer = new IndexWriter(dir,
new StopAnalyzer(Version.LUCENE_34, new File("/home/omid/Desktop/stopwords.txt")),
true,
IndexWriter.MaxFieldLength.UNLIMITED);
int numIndexed = 0;
try {
numIndexed = index(dataDir, new TextFilesFilter());
} finally {
long end = System.currentTimeMillis();
System.out.println("Indexing " + numIndexed + " files took " + (end - start) + " milliseconds");
writer.optimize();
System.out.println("Optimization took place in " + (System.currentTimeMillis() - end) + " milliseconds");
writer.close();
}
System.out.println("Enjoy your day/night");
}
public static int index(String dataDir, FileFilter filter) throws Exception {
File[] dires = new File(dataDir).listFiles();
for (File d: dires) {
if (d.isDirectory()) {
File[] files = new File(d.getAbsolutePath()).listFiles();
for (File f: files) {
if (!f.isDirectory() &&
!f.isHidden() &&
f.exists() &&
f.canRead() &&
(filter == null || filter.accept(f))) {
Thread t = new mIndexer(f);
t.start();
t.join();
}
}
}
}
return writer.numDocs();
}
private static class TextFilesFilter implements FileFilter {
public boolean accept(File path) {
return path.getName().toLowerCase().endsWith(".txt");
}
}
protected Document getDocument() throws Exception {
Document doc = new Document();
if (ifile.exists()) {
doc.add(new Field("contents", new FileReader(ifile), Field.TermVector.YES));
doc.add(new Field("path", ifile.getAbsolutePath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
String cat = "WIR";
cat = ifile.getAbsolutePath().substring(0, ifile.getAbsolutePath().length()-ifile.getName().length()-1);
cat = cat.substring(cat.lastIndexOf('/')+1, cat.length());
//doc.add(new Field("category", cat.subSequence(0, cat.length()), Field.Store.YES));
//System.out.println(cat.subSequence(0, cat.length()));
}
return doc;
}
public void run() {
try {
System.out.println("Indexing " + ifile.getAbsolutePath());
Document doc = getDocument();
writer.addDocument(doc);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
任何hep都会被视为。我认为更现代的方法是使用a并提交a,这将为您编制索引。您可以使用.awaitTermination或CountdownLatch等待所有线程终止 我不太喜欢让你的主类扩展线程,只需要创建一个可运行的内部类,在构造函数中使用它的dedencies。这使代码更具可读性,因为线程所做的工作与应用程序设置代码明显分离
关于样式的一些注意事项,我不太喜欢让你的主类抛出异常,这通常意味着你不清楚你正在使用的代码可以抛出哪些不同的检查异常。通常情况下,除非你有非常具体的原因,否则这不是正确的做法。如果你想并行化索引,可以做两件事:
- 并行化对addDocument的调用
- 增加合并计划程序的最大线程数
- 在Lucene的开发版本中有一些正在进行的工作,以改进索引并行性(特别是刷新部分,这解释了它是如何工作的)
- Lucene有一个很好的wiki页面,您可以在其中找到其他方法来提高索引速度
WaitTermination
的缺点是它不会等待所有线程完成,而是会在n个时间单位后退出-(循环是必要的。同意这一点,这将导致IndexWriter无法正确关闭。即使IndexWriter没有操纵索引目录,写入器锁仍将存在。我非常感谢您的帮助。您对线程数量的评论非常有用。我以前没有提过这一点。。。