Java RecursiveTask中是否存在对Spring托管bean的锁定

Java RecursiveTask中是否存在对Spring托管bean的锁定,java,multithreading,spring,recursion,locking,Java,Multithreading,Spring,Recursion,Locking,技术堆栈 Web应用程序 Java 1.7 Spring框架4 问题 我需要能够处理包含应用程序中文档的ZIP文件,并递归地解压缩它们。我所说的递归——如果ZIP包含其他ZIP文件,它们也应该被解压缩。然后,所有档案中的所有文件都应进行处理 第1点应并行执行,以加快流程 实施 我决定使用Java7中引入的ForkJoinFramework。因此,我最终使用了Spring管理的singleton服务ZipService(使用进程(zip)方法),该方法使用Spring管理的ForkJoinP

技术堆栈

  • Web应用程序
  • Java 1.7
  • Spring框架4
问题

  • 我需要能够处理包含应用程序中文档的ZIP文件,并递归地解压缩它们。我所说的递归——如果ZIP包含其他ZIP文件,它们也应该被解压缩。然后,所有档案中的所有文件都应进行处理

  • 第1点应并行执行,以加快流程

  • 实施

    • 我决定使用Java7中引入的ForkJoinFramework。因此,我最终使用了Spring管理的singleton服务ZipService(使用进程(zip)方法),该方法使用Spring管理的ForkJoinPool调用ZipPartitioner(我创建的一个递归任务,用于对zip文件中的内容进行分区)。ZipPartitioner
      compute()
      方法检查ZIP内容集是否足够小(文档集大小为1)以直接计算,或者是否应继续进行分区。如果应该直接计算,我会检查当前内容/文件是要处理的文件还是另一个(嵌套的)ZIP文件。有趣的是,当我在ZipService中创建ZipPartitioner时,我将
      这个
      传递给它的构造函数,因此我有一个对ZipService的引用。然后,如果在computedirectly逻辑中,它再次证明内容实际上是一个ZIP,那么我从ZipService的引用调用进程(ZIP)方法,以便该进程可以递归地重新开始
    结果

    • 令人惊讶的是,该实现工作得非常好,将处理时间缩短了3倍。然后,我决定使用测试工具对实现进行基准测试。它在5个并发请求下运行良好,但在10个以上请求时挂起。当ZipPartitioner尝试在ZipService的实例上调用进程(zip)方法时,执行会阻塞。不管在ForkJoinPool中有多少线程,我用1、10、30和1000进行了检查
    问题

    • 我认为这种方法通常是错误的——将Spring托管bean传递给RecursiveTask,但它可以处理较小的请求数。那么,有人能告诉我为什么会断裂,为什么会起作用吗?你将如何处理这个问题
    • 我怀疑对ZipService的后续请求会以某种方式使Spring锁定它,从而阻止ComputedDirectly方法的递归调用。你觉得我的想法有意义吗,还是垃圾

    让我知道我的解释中有什么不清楚的地方(我打赌会有一些不清楚的地方)。

    一些建议应该会有所帮助:

    • 执行线程转储(例如使用visualvm)并查看阻塞的内容
    • 尽量减少分叉任务的数量
    • 考虑迭代而不是递归

    为什么不尝试使用spring的@Async功能并配置一个执行器服务(一个由15个执行器组成的池)来实现这一点呢?嗯,我以前既没有使用过ForkJoin框架,也没有使用spring的@Async,我不得不选择其中一个。这是一个抛硬币的选择。我一定要去尝尝。