2015-07-28 3 views
0

Я пытаюсь запустить запуск кода 1 миллион раз. Я изначально написал его с помощью Threads, но это казалось неуклюжим. Я начал читать больше, и я наткнулся на ForkJoin. Это казалось именно тем, что мне нужно, но я не могу понять, как перевести то, что у меня есть, в «scala-style». Может ли кто-нибудь объяснить лучший способ использования ForkJoin в моем коде?ForkJoinPool для параллельной обработки

val l = (1 to 1000000) map {_.toLong} 
println("running......be patient") 
l.foreach{ x => 
    if(x % 10000 == 0) println("got to: "+x) 
    val thread = new Thread { 
     override def run { 
     //my code (API calls) here. writes to file if call success 
     } 
    } 
} 
+0

Хорошо, кто-то просветить меня бы не '(1л 1000000)' быть более эффективным, чем применение 'карты (_ toLong.)' После. факт? – jwvh

+0

Это очень вероятно, я начал изучать Scala сегодня, поэтому мой код определенно не оптимизирован. – Rilcon42

ответ

1

Самый простой способ заключается в использовании par (он будет использовать ForkJoinPool автоматически):

val l = (1 to 1000000) map {_.toLong} toList 

l.par.foreach { x => 
    if(x % 10000 == 0) println("got to: " + x) //will be executed in parallel way 
    //your code (API calls) here. will also be executed in parallel way (but in same thread with `println("got to: " + x)`) 
} 

Другой способ заключается в использовании Future:

import scala.concurrent._ 
import ExecutionContext.Implicits.global //import ForkJoinPool 

val l = (1 to 1000000) map {_.toLong} 

println("running......be patient") 

l.foreach { x => 
    if(x % 10000 == 0) println("got to: "+x) 
    Future { 
     //your code (API calls) here. writes to file if call success 
    } 
} 

Если вам нужна работа в краже - вам должен маркировать код блокировки scala.concurrent.blocking:

Future { 
    scala.concurrent.blocking { 
     //blocking API call here 
    } 
} 

Он скажет ForkJoinPool, чтобы компенсировать заблокированную нить новым - так что вы можете избежать голодания головоломки (но есть disadvantages).

+0

Спасибо за подробный ответ! Есть ли причина использовать 'Future' над' ForkJoinPool' в этом случае, если каждый вызов API полностью независим друг от друга? – Rilcon42

+1

'ForkJoinPool' - [ThreadPool] (https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html), на котором« Будущее »выполняется физически. «Будущее» - это абстракция, используемая для создания задач для ThreadPools Java (вы можете делать это вручную, но будущее проще). Вы можете больше узнать о Futures в Интернете, но ключевым преимуществом является то, что вы можете легко и без исключения извлечь результат вычисления (более-менее). + у вас есть автоматическая поддержка пулов (что у вас нет, если вы создаете потоки вручную), в том числе ForkJoin как частный случай (scala выбирает его по умолчанию). – dk14

0

В Scala можно использовать Future and Promise:

val l = (1 to 1000000) map { 
    _.toLong 
} 
println("running......be patient") 
l.foreach { x => 
    if (x % 10000 == 0) println("got to: " + x) 
    Future{ 
    println(x) 
    } 
} 
Смежные вопросы