首页 > 解决方案 > 如何在 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。我怀疑这是线程范围或线程结果合并问题,我不知道如何解决。

感谢您的帮助:)

标签: multithreadingcoldfusionluceecfspreadsheetcfthread

解决方案


多线程并不是所有问题的解决方案

这里有多个问题

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>

在 trycf.com 上查看

所以,你可以做什么

如果您确实有多个 CPU 内核,并且如果您确定解析 Excel 文件是一个缓慢的过程,那么您可能能够在单个线程中读取文件,然后将其拆分为多个部分并在多个部分中解析它们中的每一个线程。

这可能会或可能不会更有效,因为多线程会增加开销,并且您必须拆分数据,然后最后将其重新组合在一起,因此 YMMV - 您必须对此进行一些测试。

也可以看看

我建议阅读我在 Rasia.io 上发布的相关博客文章:

Lucee 中的简单并行性

Lucee 的安全并发

使用 Java 高效读取大文件的一部分


推荐阅读