multithreading - 如何在 Coldfusion/Lucee 中使用多线程编程读取大的 excel 文件?
问题描述
我正在尝试使用 10 个线程读取一个大的 excel 文件,如下面的代码所示:
<cfset var _Qry = 0 />
<cfloop from="1" to="10" index="idx">
<cfthread name="Thread#idx#" action="run" src="#arguments._file#">
<cfspreadsheet
action="read"
src="#src#"
sheet="1"
query="_Qry"
headerrow="1"
excludeHeaderRow="true">
</cfthread>
</cfloop>
<cfloop from="1" to="10" index="idx">
<cfthread name="Thread#idx#" action="join" />
</cfloop>
<cfdump var="#_Qry#">
但是当我转储_Qry
变量时,它不会产生从文件中读取的预期查询。它转储 0。我怀疑这是线程范围或线程结果合并问题,我不知道如何解决。
感谢您的帮助:)
解决方案
多线程并不是所有问题的解决方案
这里有多个问题
1) 除非您拥有像 HDFS 这样的分布式文件系统,否则这不是解决问题的好方法。一次只能有一个线程从标准文件系统中读取文件,瓶颈是文件系统而不是 CPU。
对于大数据,有一些解决方案,比如包含 HDFS 的 Hadoop 和 Apache Spark。像 HDFS 这样的分布式文件系统是专门为解决这个问题而设计的,这样您就可以并行读取大文件,您可以从具有单独磁盘的单独节点读取文件的不同部分。
2)您的代码片段“尝试”读取每个线程中的整个文件。
这意味着如果您有一个分布式文件系统,您将不会获得任何东西,因为您正在从每个节点读取整个文件。在常规文件系统上,情况要糟糕得多——由于上述瓶颈,您可能会读取文件多达 10 次。
由于大多数文件系统采用的优化和缓存,它可能不会是完整的 10 倍,但它总是比正常读取文件慢。
3) 当你调用<cfthread query="_qry" ...>
_qry 变量时被设置为线程的局部作用域,并且当线程完成执行时超出作用域。
如果希望在线程完成后能够访问它,则需要将其设置为 THREAD Scope。考虑以下示例:
<cfscript>
thread name="T1" {
x = getTickCount(); // local scope in thread T1
thread.y = round(x / 1000); // THREAD scope in thread T1
}
thread action="join";
dump(cfthread.T1.y); // will show the value of y from thread T1
// dump(cfthread.T1.x); // error, does not exist
// dump(x); // error, does not exist, this is what you have
</cfscript>
所以,你可以做什么
如果您确实有多个 CPU 内核,并且如果您确定解析 Excel 文件是一个缓慢的过程,那么您可能能够在单个线程中读取文件,然后将其拆分为多个部分并在多个部分中解析它们中的每一个线程。
这可能会或可能不会更有效,因为多线程会增加开销,并且您必须拆分数据,然后最后将其重新组合在一起,因此 YMMV - 您必须对此进行一些测试。
也可以看看
我建议阅读我在 Rasia.io 上发布的相关博客文章:
推荐阅读
- php - 即使存在 .php 扩展名,我的 Apacher 服务器也会呈现 php 文件
- monitoring - 是否有一个指标监控平台允许在指标端缓存和投资回报率开始时的时间戳
- apache-spark - AWS EMR 多作业依赖争用
- javascript - Javascript 将 CheckBox 数据表单提交给 PHP
- python - Python 上的 Unicode
- json - 如何使用 WSO2 XSLT 中介将 JSON 转换为 JSON?
- spring-integration - SI 发布-订阅通道 - 并行还是顺序执行?
- python - 使用嵌套列表或来自 2 个列表的字典创建分层字典
- ruby - Ruby、Daru、Nyaplot:将带有日期的 csv 导入数据框
- lambda - 如何让代理在埃菲尔的 {ARRAY}.do_if 工作?