RecursiveTask 中是否锁定 Spring 托管 beans
Is there locking on Spring managed beans inside RecursiveTask
技术栈
- Web 应用程序
- Java 1.7
- Spring 框架 4
问题
我需要能够在应用程序中处理包含文档的 ZIP 文件,递归地解压缩它们。我所说的递归是什么意思——如果 ZIP 包含其他 ZIP 文件,它们也应该被解压缩。然后应该处理所有档案中的所有文档。
点1应该并行执行以加快进程。
实施
- 我决定使用 Java 7 中引入的 ForkJoinFramework。所以我最终得到了 Spring 托管单例服务 ZipService(具有 process(zip) 方法),它使用 Spring managed ForkJoinPool 来调用 ZipPartitioner(一个 RecursiveTask 我为 ZIP 文件中的内容分区而创建)。 ZipPartitioner 的
compute()
方法检查 ZIP 内容集是否足够小(文档集大小为 1)以直接计算或者是否应该继续分区。如果应该直接计算它,我会检查当前 content/file 是否实际上是一个要处理的文件,或者它是另一个(嵌套的)ZIP。有趣的部分来了——当我在 ZipService 中创建 ZipPartitioner 时,我将 this
传递给它的构造函数,所以我有一个参考ZipService。然后,如果在直接计算逻辑中发现内容实际上又是一个 ZIP,我会从 ZipService' 调用 process(zip) 方法s 参考,以便该过程可以递归地重新开始。
结果
- 令人惊讶的是,实施工作非常顺利,处理时间减少了 3 倍。然后我决定用 JMeter 对实现进行基准测试。它在 5 个并发请求下运行良好,但在 10 个以上请求时挂起。当 ZipPartitioner 尝试调用 ZipService 实例上的 process(zip) 方法时,执行阻塞. ForkJoinPool 中有多少个线程并不重要 - 我检查了 1、10、30 和 1000。
问题
- 我认为这种方法通常存在一些错误 - 将 Spring 托管 bean 传递给 RecursiveTask,但它适用于较小的请求数。那么有人能告诉我为什么会这样吗?为什么会这样?你会如何解决这个问题?
- 我怀疑对 ZipService 的后续请求会以某种方式 Spring 锁定它,从而阻止来自 computeDirectly 方法的递归调用。你觉得我的想法有意义还是垃圾?
让我知道我解释中不清楚的地方(我敢打赌会有一些东西)。
一些应该有用的建议:
- 执行线程转储(例如使用 visualvm)并查看被阻止的内容
- 尽量减少分叉任务的数量
- 考虑迭代而不是递归
技术栈
- Web 应用程序
- Java 1.7
- Spring 框架 4
问题
我需要能够在应用程序中处理包含文档的 ZIP 文件,递归地解压缩它们。我所说的递归是什么意思——如果 ZIP 包含其他 ZIP 文件,它们也应该被解压缩。然后应该处理所有档案中的所有文档。
点1应该并行执行以加快进程。
实施
- 我决定使用 Java 7 中引入的 ForkJoinFramework。所以我最终得到了 Spring 托管单例服务 ZipService(具有 process(zip) 方法),它使用 Spring managed ForkJoinPool 来调用 ZipPartitioner(一个 RecursiveTask 我为 ZIP 文件中的内容分区而创建)。 ZipPartitioner 的
compute()
方法检查 ZIP 内容集是否足够小(文档集大小为 1)以直接计算或者是否应该继续分区。如果应该直接计算它,我会检查当前 content/file 是否实际上是一个要处理的文件,或者它是另一个(嵌套的)ZIP。有趣的部分来了——当我在 ZipService 中创建 ZipPartitioner 时,我将this
传递给它的构造函数,所以我有一个参考ZipService。然后,如果在直接计算逻辑中发现内容实际上又是一个 ZIP,我会从 ZipService' 调用 process(zip) 方法s 参考,以便该过程可以递归地重新开始。
结果
- 令人惊讶的是,实施工作非常顺利,处理时间减少了 3 倍。然后我决定用 JMeter 对实现进行基准测试。它在 5 个并发请求下运行良好,但在 10 个以上请求时挂起。当 ZipPartitioner 尝试调用 ZipService 实例上的 process(zip) 方法时,执行阻塞. ForkJoinPool 中有多少个线程并不重要 - 我检查了 1、10、30 和 1000。
问题
- 我认为这种方法通常存在一些错误 - 将 Spring 托管 bean 传递给 RecursiveTask,但它适用于较小的请求数。那么有人能告诉我为什么会这样吗?为什么会这样?你会如何解决这个问题?
- 我怀疑对 ZipService 的后续请求会以某种方式 Spring 锁定它,从而阻止来自 computeDirectly 方法的递归调用。你觉得我的想法有意义还是垃圾?
让我知道我解释中不清楚的地方(我敢打赌会有一些东西)。
一些应该有用的建议:
- 执行线程转储(例如使用 visualvm)并查看被阻止的内容
- 尽量减少分叉任务的数量
- 考虑迭代而不是递归