zoukankan      html  css  js  c++  java
  • [Lucene.Net] 多线程操作建议和[Lucene.Net] 分页显示

    对于并发,Lucene.Net 遵循以下规则:

    1. 允许任意多的读操作并发,即任意数量用户可同时对同一索引做检索操作。
    2. 即便正在进行索引修改操作(索引优化、添加文档、删除文档),依然允许任意多的检索操作并发执行。
    3. 不允许并发修改操作,也就是说同一时间只允许一个索引修改操作。

    Lucene.Net 内部已经对多线程安全进行了处理,打开 IndexWrite.cs / IndexReade.csr 文件,会发现很多操作都使用了 lock 进行多线程同步锁定。只要遵循一定的规则,就可以在多线程环境下安全运行 Lucene.Net。

    建议:

    1. Directotry、Analyzer 都是多线程安全类型,只需建立一个 Singleton 对象即可。
    2. 所有线程使用同一个 IndexModifier 对象进行索引修改操作。
    3. IndexWriter/IndexReader/IndexModifier/IndexSearcher 最好使用同一个 Directory 对象,否则多线程并发读写时可能引发 FileNotFoundException。

    IndexModifier 对象封装了 IndexWriter 和 IndexReader 的常用操作,其内部实现了多线程同步锁定。使用 IndexModifier 可避免同时使用 IndexWriter 和 IndexReader 时需要在多个对象之间进行同步的麻烦。等所有修改操作完成后,记住调用 Close() 方法关闭相关资源。并不是每次操作都需要调用 Optimize(),可以依据特定情况,定期执行优化操作。

    --------

    以下演示代码简单封装了一个 IndexModifier Signleton 类型,确保多线程使用同一个对象,且只能由最后一个多线程调用 Close 方法关闭。
    代码不完善,仅供参考!需要做些修改才能应用于实际项目。
    public class MyIndexModifier
    {
      private static Directory directory = new RAMDirectory();
      private static Analyzer analyzer = new StandardAnalyzer();
      private static IndexModifier modifier;
      private static List<Thread> threadList = new List<Thread>();
      
      private MyIndexModifier() { }

      public static IndexModifier GetInstance()
      {
        lock (threadList)
        {
          if (modifier == null)
          {
            modifier = new IndexModifier(directory, analyzer, false);
            modifier.SetMaxFieldLength(1000);
          }

          if (!threadList.Contains(Thread.CurrentThread))
            threadList.Add(Thread.CurrentThread);

          return modifier;
        }
      }

      public static void Close()
      {
        lock (threadList)
        {
          if (threadList.Contains(Thread.CurrentThread))
            threadList.Remove(Thread.CurrentThread);

          if (threadList.Count == 0)
          {
            if (modifier != null)
            {
              modifier.Close();
              modifier = null;
            }
          }
        }
      }
    }

    多线程测试代码
    for (int i = 0; i < 100; i++)
    {
      new Thread(delegate()
      {
        IndexModifier writer = MyIndexModifier.GetInstance();

        for (int x = 0; x < 10; x++)
        {
          Document doc = new Document();
          doc.Add(Field.Text("a", "Hello, World!"));
          writer.AddDocument(doc);
        }

        Console.WriteLine("{0}: {1}", Thread.CurrentThread.ManagedThreadId, writer.DocCount());
        MyIndexModifier.Close(); // 注意不是调用 IndexModifier.Close() !

      }).Start();
    }

    很简单,依照以下公式计算几个数据即可。

    索引库文档总数
    DocumentCount = searcher.Reader.NumDocs();

    搜索结果总数
    Count = Hits.Length();

    每页记录数
    PageSize;

    结果页总数 (注意处理余数)
    PageCount = (Count / PageSize) + (Count % PageSize > 0 ? 1 : 0);

    要显示的页序号 (当页序号大于页总数时,返回最后一页。)
    PageIndex = Math.Min(PageIndex, PageCount);

    起始记录序号 (起始序号必须大于等于零)
    StartPos = Math.Max((PageIndex - 1) * PageSize, 0);

    结尾记录序号 (不能大于记录总数)
    EndPos = Math.Min(PageIndex * PageSize - 1, Count - 1);


    演示:返回第10页,每页20条记录。

    Hits hits = searcher.Search(query);

    int pageIndex = 10;
    int pageSize = 20;
    int count = hits.Length();

    if (count > 0)
    {
      int pageCount = count / pageSize + (count % pageSize > 0 ? 1 : 0);
      pageIndex = Math.Min(pageIndex, pageCount);
      int startPos = Math.Max((pageIndex - 1) * pageSize, 0);
      int endPos = Math.Min(pageIndex * pageSize - 1, count - 1);

      for (int i = startPos; i <= endPos; i++)
      {
        int docId = hits.Id(i);
        string name = hits.Doc(i).Get(FieldName);
        float score = hits.Score(i);

        Console.WriteLine(" DocId:{0}; Name:{1}; Score:{2}", docId, name, score);
      }
    }

    作者: yuhen

  • 相关阅读:
    python基础_类的继承
    python基础_命名规范
    jmeter分布式压测(linux)
    Jmeter压测报错java.net.BindException: Address already in use: connect
    分布式压测平台之Ngrinder(安装篇)
    关于TeamCenter流程开发Handler问题
    C语言中的指向运算符:->
    Eclipse Action与Command的区别
    Eclipse开发RCP项目的plugin.xml详解
    Swing中通过按钮对表格JTable选中行对象进行上移和下移的操作
  • 原文地址:https://www.cnblogs.com/peida/p/1341925.html
Copyright © 2011-2022 走看看