Как прочитать большой файл Excel, используя многопоточное программирование в Coldfusion/Lucee?
Я пытаюсь прочитать большой файл Excel с использованием 10 потоков, как показано в коде ниже:
<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 ответ
Многопоточность - это не решение каждой проблемы
Здесь есть несколько вопросов
1) Если у вас нет распределенной файловой системы, например, HDFS, это не очень хороший подход к проблеме. Только один поток может одновременно читать файл из стандартной файловой системы, и узким местом является файловая система, а не центральный процессор.
Для больших данных есть такие решения, как Hadoop, который содержит HDFS, и 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>
Так что ты можешь сделать
Если у вас есть несколько ядер ЦП, и если вы решите, что синтаксический анализ файла Excel является медленным процессом, вы можете прочитать файл в одном потоке, но затем разбить его на несколько частей и проанализировать каждое из них в нескольких потоки.
Это может быть или не быть более эффективным, так как многопоточность увеличивает накладные расходы, и вам придется разделить данные, а затем собрать их вместе, в конце концов, так что YMMV - вам нужно провести некоторое тестирование для этого.
Смотрите также
Я рекомендую прочитать соответствующие сообщения в блоге, которые я опубликовал на Rasia.io:
Использование Java для эффективного чтения части большого файла