2017-06-07 16 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秒等等,但我们总是尽力优化我们的程序。