6

I have a large processing task which I believe is ripe for being made more efficient with concurrency and parallelism.

I had a look at the GPars docs and I found them quite confusing so I hope people here can help.

The first task I would like to do in parallel currently looks like this:

def providerOneProgrammes = providerOneProgrammeService.getProgrammes(timeWindow)
def providerTwoProgrammes = providerTwoProgrammeService.getProgrammes(timeWindow)

both return a list of objects and both can be run in parallel.

I would like to execute them together and then wait for them to finish before processing the return lists (I will then look for matches between the lists but I'll come to that later).

Thanks

Rakesh

Arturo Herrero
  • 12,772
  • 11
  • 42
  • 73
FinalFive
  • 1,465
  • 2
  • 18
  • 33

1 Answers1

14

The simplest way to take advantage of GPars here is with callAsync. Here's a simple example:

@Grab(group='org.codehaus.gpars', module='gpars', version='1.0-beta-2')

import groovyx.gpars.GParsPool

def providerOneProgrammeService(timeWindow) {
    println "p1 starts"
    Thread.sleep(4000)
    println "p1 still going"
    Thread.sleep(4000)
    println "p1 ends"
    return "p1 return value"
}

def providerTwoProgrammeService(timeWindow) {
    println "p2 starts"
    Thread.sleep(5000)
    println "p2 still going"
    Thread.sleep(5000)
    println "p2 still going"
    Thread.sleep(5000)
    println "p2 ends"
    return "p2 return value"
}

def results = []
GParsPool.withPool {
    results << this.&providerOneProgrammeService.callAsync("arg1")
    results << this.&providerTwoProgrammeService.callAsync("arg2")
}
println "done ${results*.get()}"
ataylor
  • 64,891
  • 24
  • 161
  • 189
  • groovy did not like the results.*get() syntax. Calling with out the * causes an exception. – FinalFive Jul 18 '12 at 16:00
  • Sorry, that should be results*.get(). I've fixed the answer. – ataylor Jul 18 '12 at 16:18
  • thanks for the example, its enough to get me started exploring GPars. – FinalFive Jul 19 '12 at 08:21
  • I could be wrong but on page 15 of the gpars guide it says adding to a collection like your example is a BAD thing. Can you confirm? – FinalFive Jul 22 '12 at 19:35
  • 1
    That example (`images.eachParallel {thumbnails << it.thumbnail}`) appends to the collection from multiple threads. My example runs the appends synchronously. Only the `provider...` methods themselves get run asynchronously. It might be less confusing when you note that the return value from callAsync is a [`Future`](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html) which just acts as a placeholder for the result until `get` is called. – ataylor Jul 23 '12 at 20:36
  • what if the two lists are different? I don't actually want them merged together. – FinalFive Aug 01 '12 at 15:55
  • Why do you need this `results[]` list? Does it help with synchronization? – IgorGanapolsky Oct 14 '16 at 20:28