技术堆栈
Web应用程序 Java 1.7 Spring框架4
问题
我需要能够处理包含应用程序中文档的ZIP文件,并以递归方式解压缩它们。我的意思是递归-如果ZIP包含其他ZIP文件,它们也应该解压缩。然后,应处理所有存档中的所有文档。 点1应该并行执行,以加快处理速度。
实现
我决定使用Java 7中引入的ForkJoinFramework。因此,我最终得到了Spring托管的单例服务 ZipService (具有进程(zip)方法),该方法使用Spring托管的 ForkJoinPool 来调用(Zipition) RecursiveTask 我创建用于对ZIP文件中的内容进行分区)。 ZipPartitioner 的compute()
方法检查ZIP内容集是否足够小(文档集大小为1)以直接计算或是否应该继续进行分区。如果应该直接计算,请检查当前内容/文件是否实际上是要处理的文件,还是另一个(嵌套的)ZIP。这是一个有趣的部分-当我在 ZipService 中创建 ZipPartitioner 时,我将this
传递给其构造函数,因此我对 ZipService 进行了引用。然后,如果直接在计算逻辑中发现内容实际上又是一个ZIP,我从 ZipService 的引用中调用进程(zip)方法,以便该过程可以递归地重新开始。
结果
令人惊讶的是,该实现效果很好,并且将处理时间缩短了3倍。然后,我决定使用JMeter对实现进行基准测试。它可以同时处理5个并发请求,但可以处理10个以上的请求。当 ZipPartitioner 尝试在 ZipService 的实例上调用进程zipt_rstrong方法时,执行将阻塞。 ForkJoinPool 中有多少个线程都没关系-我用1、10、30和1000进行了检查。
问题
我认为这种方法通常存在一些错误-将Spring托管的bean传递给RecursiveTask,但是它可以处理较小的请求数。那么有人能指出我为什么会中断以及为什么会起作用吗?您将如何解决这个问题? 我怀疑随后对ZipService的请求以某种方式使Spring锁定了它,并且这种方式阻止了generateDirectly方法的递归调用。您是否在我的想法中发现了有意义的东西,或者它们是垃圾?
让我知道我的解释中有哪些不清楚的地方(我敢打赌会有些东西)。 一些建议应该会有所帮助:
执行线程转储(例如,使用visualvm),并查看阻止的尝试最小化 fork 任务的数量考虑迭代而不是递归09-07 20:11