2

我试图提高索引我的lucene文件的性能。为此,我创建了一名工作人员“LuceneWorker”来完成这项工作。设计问题:这只适用于生产者/消费者吗?

鉴于下面的代码,'并发'执行变得非常慢。我想我知道为什么 - 这是因为期货增长到极限,几乎没有内存可以执行LuceneWorker的另一项任务。

问:有没有办法限制进入执行者的“工人”数量?换句话说,如果有'n'期货 - 不要继续并且允许文件首先被索引?

我的直观方法是我应该用ArrayBlockingQueue构建一个消费者/生产者。但是,在我重新设计它之前,我想知道我是否合适。

 ExecutorService executor = Executors.newFixedThreadPool(cores); 
     List<Future<List<Document>>> futures = new ArrayList<Future<List<Document>>>(3); 
     for (File file : files) 
     { 
      if (isFileIndexingOK(file)) 
      { 
       System.out.println(file.getName()); 
       Future<List<Document>> future = executor.submit(new LuceneWorker(file, indexSearcher)); 
       futures.add(future); 
      } 
      else 
      { 
       System.out.println("NOT A VALID FILE FOR INDEXING: "+file.getName()); 
       continue; 
      } 
     } 

     int index=0; 
     for (Future<List<Document>> future : futures) 
     { 
      try{ 

       List<Document> docs = future.get(); 

       for(Document doc : docs) 
        writer.addDocument(doc);  


      }catch(Exception exp) 
      { 
       //exp code comes here. 
      } 
     } 

回答

1

如果你想限制等待作业的数量,使用ThreadPoolExecutor与像ArrayBlockingQueue有界队列。同时滚动您自己的RejectedExecutionHandler,以便提交线程等待队列中的容量。您无法使用Executors中的便利方法,因为newFixedThreadPool使用无限制的LinkedBlockingQueue

1

根据标准输入大小和LuceneWorker类的复杂性,我可以想象至少部分地使用Fork/Join框架来解决这个问题。当使用JDK 8的CountedCompleter实现(包含在jsr166y中)时,I/O操作不会产生任何问题。