2017-06-07 56 views
0

我試圖用BlockingQueue實現一些Consumer-Producer問題。爲了達到某種目的,我決定編寫文件搜索工具。Java。消費者 - 製造商與BlockingQueue。搜索工具

我決定搜索機制是遞歸的工作,並且每個新目錄都會有新的線程池來提高搜索速度。

我的問題是,我不知道如何實現停止打印線程(消費者)在最後的機制 - 當搜索線程完成工作。

我試圖用POISON PILLS等一些想法做到這一點,但它不能很好地工作(線程在打印任何結果之前停止)。任何想法我怎麼能做到這一點?

下面是一些代碼:

搜索機制:

public class SearchingAlgorithm implements Runnable { 

private final File file; 
private BlockingQueue<File> queue; 
private ExecutorService executor; 

public SearchingAlgorithm(File fileName, BlockingQueue<File> queue) { 
    this.file = fileName; 
    this.queue = queue; 
    this.executor = Executors.newWorkStealingPool(); 
} 

@Override 
public void run() { 
    try { 
     searchDeep(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

private void searchDeep() throws InterruptedException { 
    File[] files = file.listFiles(); 
    if (files != null) { 
     for (File fil : files) { 
      if (fil.isDirectory()) { 
       executor.submit(new SearchingAlgorithm(fil, this.queue)); 
      } else { 
       this.queue.add(fil); 
      } 
     } 
    } 
} 

}

打印機:

public class ContainingCheckAlgorithm implements Runnable { 

private BlockingQueue<File> queue; 
// private ExecutorService executor; 
private String keyWord; 

public ContainingCheckAlgorithm(BlockingQueue<File> queue, String keyWord) { 
    this.queue = queue; 
    this.keyWord = keyWord; 
    // executor = Executors.newFixedThreadPool(2); 
} 

@Override 
public void run() { 
    try { 
     printFile(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

} 

private void printFile() throws InterruptedException { 
    while (true) { 
     File takeFile = queue.take(); 
     String fileName = takeFile.getAbsolutePath() 
       .toLowerCase(); 
     boolean isContainingKeyWord = fileName.contains(keyWord.toLowerCase()); 

     if (isContainingKeyWord) { 
      System.out.println(takeFile.getAbsolutePath()); 
     } 
    } 
} 

}

主要測試類:

public class MainClass { 

public static void main(String[] args) throws InterruptedException { 
    ExecutorService executor = Executors.newFixedThreadPool(2); 
    BlockingQueue<File> queue = new LinkedBlockingQueue<>(); 

    File fileName = new File("C:/"); 

    SearchingAlgorithm sa = new SearchingAlgorithm(fileName, queue); 
    executor.submit(sa); 

    ContainingCheckAlgorithm ca = new ContainingCheckAlgorithm(queue, "Slipknot"); 
    executor.submit(ca); 

    executor.shutdown(); 
} 

}

回答

0

斯普利特在2個階段的全部工作。在第一階段,如果隊列爲空,SearchingAlgorithm的工作和ContainingCheckAlgorithm會等待新的作業。在第二階段,所有SearchingAlgorithm實例完成,如果發現隊列爲空,則ContainingCheckAlgorithm退出。爲了發現隊列是否爲空,ContainingCheckAlgorithm使用queue.poll(timeout)而不是queue.take()。

而且您無需爲每個SearchingAlgorithm創建新的線程池。

0

如u說,我嘗試做這種方式:

搜索與searchingAlgorithm他人insatances算法份額線程池。

查詢:

​​

現在ContainingCheckAlgorith需要與主類共享CountDownLatch,因爲我需要一些機制來關閉線程池的主類。它也會像你說的那樣使用池(超時),我的線程最終完成了它的工作。

正在檢查

public class ContainingCheckAlgorithm implements Runnable { 

private BlockingQueue<File> queue; 
private String keyWord; 
private CountDownLatch latch; 

public ContainingCheckAlgorithm(BlockingQueue<File> queue, String keyWord, CountDownLatch latch) { 
    this.queue = queue; 
    this.keyWord = keyWord; 
    this.latch = latch; 
} 

@Override 
public void run() { 
    try { 
     printFile(); 
     latch.countDown(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

} 

private void printFile() throws InterruptedException { 
    File takeFile; 
    while ((takeFile = queue.poll(1, TimeUnit.SECONDS)) != null) { 
     String fileName = takeFile.getName() 
       .toLowerCase(); 
     boolean isContainingKeyWord = fileName.contains(keyWord.toLowerCase()); 

     if (isContainingKeyWord) { 
      System.out.println(takeFile.getAbsolutePath()); 
     } 
    } 
} 

MAIN:

public class MainClass { 

public static void main(String[] args) throws InterruptedException { 
    ExecutorService executor = Executors.newCachedThreadPool(); 
    BlockingQueue<File> queue = new LinkedBlockingQueue<>(); 
    CountDownLatch latch = new CountDownLatch(1); 

    File fileName = new File("C:/"); 

    SearchingAlgorithm sa = new SearchingAlgorithm(fileName, queue, executor); 
    executor.submit(sa); 

    ContainingCheckAlgorithm ca = new ContainingCheckAlgorithm(queue, "Slipknot", latch); 
    executor.submit(ca); 

    latch.await(); 
    executor.shutdown(); 
} 

它看起來怪異,但我不知道是什麼:

  • 多個線程將運行作爲ContainingCheckAlgorithm ?

  • SearchingAlgorithm將搜索超過1秒的文件,並ContainingCheckAlgorithm完成工作?顯然,我可以將超時更改爲2秒等等,但我們總是盡力優化我們的程序。