首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Lucene 3.0.0 核心細節探秘(一):Consumer 與 Processor 執行緒模型深度剖析

     編輯:關於.NET

前言

對 Lucene 3.0.0 的執行緒模型極感興趣。個人十年程式生涯缺憾:未寫過網路、多執行緒、資料庫、Linux 程式。6 年鞏固演算法基礎,4 年摸索 3D 遊戲 AI。希望在未來幾年補齊成為「萬金油」。研讀開源框架重在「研究」而非「使用」,工作後壓力易使人浮躁,趁早打好基礎。計劃在掌握原始碼後用 C++ 重寫關鍵路徑(工作語言為 C++)。轉貼請註明出處:leftnoteasy.cnblogs.com。

Consumer/Processor 類別關係圖

UML 類別圖

直接相關類別眾多,且部分抽象類方法雖相同但未用繼承(避免 RTTI 問題),初讀易混淆。

1. DocFieldProcessor、DocFieldProcessorPerThread、DocInverter

Processor 階層

DocFieldProcessor

繼承 DocConsumer(最高層 Consumer)。註解說明:

收集同名 Field,呼叫 per-field consumer 處理,本身不做「實際」工作,只轉發。


public void flush(Collection<DocConsumerPerThread> threads, SegmentWriteState state) {
    Map<DocFieldConsumerPerThread, Collection<DocFieldConsumerPerField>> childThreadsAndFields = 
        new HashMap<...>();
    for (DocConsumerPerThread thread : threads) { ... }
}

實際委派給多個 DocFieldProcessorPerThread。

DocFieldProcessorPerThread

繼承 DocConsumerPerField,核心在 processDocument()(100+ 行):

  1. 收集 Field,檢查是否新增,擴充雜湊
  2. 對 Field 排序(quickSort())
  3. 逐個 Field 呼叫其 consumer(基類 DocFieldConsumerPerField)

DocInverter

對來自同一文件的每個 Field 獨立進行倒排,接受 InvertedTermsConsumer 處理術語。

2. DocInverterPerField、TermsHashPerField

Inverter 階層

DocInverterPerField

由 DocProcessorPerThread.processDocument() 呼叫:


for (int i = 0; i < fieldCount; i++)
    fields[i].consumer.processFields(fields[i].fields, fields[i].fieldCount);

註解:保存單一文件中單一 field 的倒排狀態,自身不處理,轉發 token 給自有 consumer(InvertedDocConsumerPerField),並與 endConsumer(InvertedDocEndConsumerPerField)互動。

processFields 主要:判斷是否需分析(tokenized),否則直接放入字串;呼叫自有 consumer。

TermsHashPerField

由 DocInverterPerField 呼叫。初始化:


@Override
public void processFields(final Fieldable[] fields, final int count) {
    // ...
    boolean hasMoreTokens = stream.incrementToken();
    fieldState.attributeSource = stream;
    OffsetAttribute offsetAttribute = fieldState.attributeSource.addAttribute(OffsetAttribute.class);
    PositionIncrementAttribute posIncrAttribute = fieldState.attributeSource.addAttribute(PositionIncrementAttribute.class);
    consumer.start(field);
    // ...
}

TermsHashPerField.start():


@Override
void start(Fieldable f) {
    termAtt = fieldState.attributeSource.addAttribute(TermAttribute.class);
    consumer.start(f);
    if (nextPerField != null) nextPerField.start(f);
}

初始化 termAtt(TokenStream 相關屬性)。核心 add()(~150 行):

  1. 取得 token 文本
  2. 雜湊處理、移除無效字元
  3. 術語已存在 → consumer.addTerm();新術語 → consumer.newTerm()

3. TermVectorsTermsWriterPerField、FreqProxTermsWriterPerField

Writer 階層

繼承 TermsHashConsumerPerField。前者僅當 Field 指定 TermVector 儲存時啟用。兩者皆有 addTerm/newTerm,邏輯複雜,擬另文專述緩衝區相關細節。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved