我有一些处理大约30,000条记录的代码。基本大纲是这样的:
startRecordID = 2345;
endRecordID = 32345;
for(recordID=startRecordID; recordID <= endRecordID; recordID++){
// process record...
}
现在,这个处理需要很长时间,我想拥有一个包含15个线程的线程池,并为每个线程提供一个要处理的recordID列表,然后在最后加入它们。
在过去,我使用类似于此的代码完成了此操作,其中recordLists
是一个子数组数组,每个子数组包含要处理的1/15记录:
<cfset numThreads = 15 />
<!--- keep a running list of threads so we can join them all at the end --->
<cfset threadlist = "" />
<cfloop from="1" to="#numThreads#" index="threadNum">
<cfset threadName = "recordProcessing_#threadNum#" />
<cfset threadlist = listAppend(threadlist, threadName) />
<cfthread action="run" name="#threadName#" recordList="#recordList[threadNum]#">
<cfloop from="1" to="#ArrayLen(recordList)#" index="recordIndex">
<cfset recordID = recordList[recordIndex] />
... process recordID ...
</cfloop>
</cfthread>
</cfloop>
<!--- Join all threads before continuing --->
<cfthread action="join" name="#threadlist#" timeout="4000"/>
这很好用(虽然我也会将这个旧代码转换为cfscript :))但是要创建recordLists子数组的数组并不是那么简单......我能想到的方法就是循环遍历startRecordID-endRecordID中的数字,将每个数字添加到一个数组,然后在其上运行一个ArrayDivide函数(我们已经在我们的代码库中定义)将其拆分为numThreads(在本例中为15)相等的子数组。考虑到我有范围的开始,范围的结束,以及我希望将其划分的线程数,是不是有更简单的方法来分解它并将其分配给线程?
答案 0 :(得分:3)
(来自评论..)
如果你已经有一个阵列,为什么要再次循环呢?没有内置函数,但由于数组是java List
,因此简单的yourArray.subList(startIndex, endIndex)
就可以了。显然,如果记录数小于处理线程数,则添加一些错误处理。
NB:由于它是一个java方法,索引从零开始(0),endIndex
是独占。此外,在大多数方面,结果是类似 CF阵列。但是,它是不可变的,即无法修改。
<cfscript>
// calculate how many records to process in each batch
numOfIterations = 15;
totalRecords = arrayLen(recordsArray);
batchSize = ceiling(totalRecords/numOfIterations);
for (t=0; t < numOfIterations; t++) {
// calculate sub array positions
startAt = t * batchSize;
endAt = Min(startAt+batchSize, totalRecords);
// get next batch of records
subArray = recordsArray.subList(startAt, endAt);
// kick off a thread and do whatever you want with the array ...
WriteOutput("<br>Batch ["& t &"] startAt="& startAt &" endAt="& endAt);
}
</cfscript>