Reputation: 21496
I have a list of hundreds of thousands of tasks that needs to be done (in any order). It takes several hours to run through them all. I figure a good way of speeding it up would be to try running it in parallel.
Here's a minimal reproduction of the code that's single threaded and works fine:
doTask = { more ->
println("Start")
sleep 10000 // sleep 10 seconds
println("Finish")
}
(1..3).each{ more -> doTask(more) }
I have no prior experience with Groovy so this functional syntax is a bit alien to me... but I found a lot of questions on SO where people suggested that you check this page:
http://groovy.codehaus.org/Concurrency+with+Groovy
Linkrot has occured - that page no longer exists, but I did find an archive of it here:
https://web.archive.org/web/20150102212441/http://groovy.codehaus.org/Concurrency+with+Groovy
I tried adapting the examples from that page and ended up with this:
import java.util.concurrent.*
pool = Executors.newFixedThreadPool(3)
defer = {c -> pool.submit(c as Callable) }
doTask = { more ->
println("Start")
sleep 10000 // sleep 10 seconds
println("Finish")
}
(1..3).each{ more -> defer{doTask(more)} }
When I run it over here: http://groovyconsole.appspot.com/
I get this error:
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
at Script1$_run_closure1.doCall(Script1.groovy:5)
at Script1$_run_closure3.doCall(Script1.groovy:12)
at Script1.run(Script1.groovy:12)
What's going on? Have I somehow messed up the syntax? Am I misusing an API? Is this maybe just a limitation of that website?
Upvotes: 0
Views: 2655
Reputation: 13690
No, this code runs fine for me... the Exception is probably because the appspot webconsole you're using does not allow multi-threaded applications to run.
Download Groovy and run it with the Groovy Console, it will work fine.
But here's a suggestion for simplifying your code a little bit:
import java.util.concurrent.Callable
import java.util.concurrent.Executors
pool = Executors.newFixedThreadPool( 3 )
doTask = { more ->
println "Start"
sleep 10000 // sleep 10 seconds
println "Finish"
}
( 1..3 ).each { more -> pool.submit { doTask( more ) } }
In Groovy, anything between curly braces is a closure you can submit to the pool.
So pool.submit { /* any code here to run async */ }
works.
Upvotes: 3