Java多线程文件系统树遍历

时间:2011-09-21 11:46:44

标签: java concurrency

我的采访有点任务(原文如此!) 我需要创建java CLI程序来搜索匹配某些模式的特定文件。他们说我需要使用多线程方法而不使用util.concurrent包并在并行控制器上提供良好的性能。

从我的观点来看,它非常简单 - 我可以为每个子文件夹创建特定的线程并运行它的内容,并为每个子文件夹运行另一个线程...
但它不是那么容易:)也许有人可以告诉我我应该知道的典型陷阱。或者,任何有关在Java中实现此方法的建议都将受到高度赞赏。

谢谢!

UPD1
文件名应与模式匹配。

4 个答案:

答案 0 :(得分:3)

问题在于找到大量的线程并尽可能平等地分配作品。

假设您不知道每个文件夹中的文件和子目录的数量,这可能会变得非常棘手。

这是一个开始的想法:

你可能会做的是创建一些在中央文件夹列表上运行的线程,并为每个遇到的文件夹生成一个线程,直到达到某个最大值。然后,每个线程都可以将其工作目录的子文件夹放到中央列表中,一旦完成,它就可以从该列表中选择下一个。

如果列表中放置了一个文件夹并且未达到最大线程数,则会立即生成一个新线程。

如果线程已用尽且文件夹列表为空,则可能会停止(要求您在需要时生成新文件)或等到列表中有文件夹或应用程序发出所有文件夹信号正在处理。

最后,不要忘记在文件夹列表上进行同步。

希望能帮助您入门。


修改 :(不要太认真地对待以下内容:))

您还可以使用另一个不使用java.util.concurrent包的线程池实现:)

编辑2 :基本上我上面描述的是一个简单且特定于任务的线程池实现。您可以尝试自己查找有关构建线程池的更多信息(在您的分配上下文中,线程池任务将扫描一个文件夹)。

答案 1 :(得分:2)

在我的脑海中,我可以想到几种方法,我将在这里开始概述。如果您需要更详细的解释,我很乐意详细说明。请注意,我已经 NOT 尝试编码来测试其中任何一个(还是),所以请带上它们。

第一种方法依赖于中央调度程序(主线程)来协调工作线程池和“工作”队列(文件夹)。中央调度程序将线程池初始化为其最小大小,并将根文件夹分配给第一个工作线程,然后通知它唤醒。

每个工作线程都以空闲状态启动,循环直到收到“唤醒”信号。然后检查是否已为其分配了要处理的文件夹,并开始迭代该文件夹的内容。工作线程将与模式匹配的任何文件提交到“找到”列表(或者只将其打印到System.out)。

将任何子文件夹添加回“工作”队列(并发出主线程信号)。然后,工作线程重新进入“空闲”状态(并再次发出主线程信号)。在醒来时,应该为它分配一个新文件夹,它以相同的方式开始处理。否则,线程可以自行终止。

主线程等待,直到它收到来自任何工作线程的信号。它首先检查工作队列是否为空。如果没有,则检查是否有任何空闲的工作线程。虽然有任何空闲的工作线程(并且工作队列非空),但是将第一个文件夹弹出工作队列并将其分配给该线程,并发出信号以唤醒它。主线程然后回到等待。

如果没有空闲线程,则检查当前线程池大小与最大配置大小。如果池已经达到最大值,那么主线程将返回休眠状态(基本上等待线程变为空闲)。否则,当池不是最大值时,创建一个新线程,将其添加到池中,并将其分配给工作队列中的第一个文件夹,然后将其唤醒。

如果主线程在工作队列为空时唤醒,则首先检查是否有空闲线程且工作线程池是否大于配置的最小值。如果是这样,主线程可以选择唤醒空闲线程(没有分配文件夹,因此它们将终止)并从池中删除它们。如果线程池已经处于最小值,则主线程再次返回等待。请注意,这种“缩小规模”步骤可能是不必要的优化(因为工作线程不应该消耗等待的CPU周期)。

如果所有线程都空闲,则工作队列为空,则主线程知道它已完成,并且可以通知所有剩余的工作线程唤醒并自行终止。< / p>

这里的诀窍在于主线程和工作线程之间的信号传递,以及工作队列上的同步(以及可能的'找到文件'bin)。

(另外,为了简化一点,可以选择固定大小的线程池。)


替代方法不涉及中央调度员,而是使用固定的工作线程池,以随机间隔休眠,定期唤醒以检查a)工作队列是否有项目,或b)所有工作是否已完成完成。

主线程只是初始化线程池,将根文件夹放在工作队列的头部,然后启动所有工作线程。然后它等待一个信号告诉它所有的工作都已完成并且它可以清理(中断所有剩余的工作线程以唤醒它们并自行终止)。

每个工作线程都以非空闲状态启动并检查工作队列。第一个线程应该看到根文件夹,它从队列中弹出并开始处理它,类似于上面的。启动时所有其他线程应该看到一个空队列并进入休眠状态。

当一个工作线程被唤醒时,它会检查工作队列是否还有待处理的文件夹,如果是,则对其进行处理,将其“idle”标志设置为false。完成当前文件夹后,它会再次检查工作队列。如果工作队列为空,则设置其“空闲”标志。

当工作线程找到一个空队列时(在唤醒或处理后),它会检查所有其他线程是否“闲置”。如果它发现至少有一个其他线程仍在工作,那么它会以随机间隔进入休眠状态。

如果所有其他线程都“空闲”且工作队列为空,则线程可以自行终止。在这样做之前,它会中断或发出主线程的信号,因此主线程可以为其他线程进行清理。

这种方法也可以适用于使用灵活大小的线程池,它可以根据需要动态增长或缩小,但这只会将更复杂的逻辑放入工作线程中,我现在不会讨论这些。

答案 2 :(得分:0)

您可能需要考虑使用ExecutorService来控制任何时候创建/运行的线程数。

答案 3 :(得分:0)

您可以使用JNI并为该模式调用操作系统的搜索过程。

我的假设是操作系统会比你做得更有效率。

使用多线程只是为了产生JNI并解析结果。