Groovy is a very pragmatic language. It keeps ceremony to the minimum while taking advantage of the mighty JVM and the Java platform. The GPars library is a convenient way to run computations in parallel, async or concurrent. The same thing can be achieved to an extend with plain Java with the java.util.concurrent.*
classes. An article by Edgardo Hernandez demonstrates the usage with Java. Let's use Groovy and GPars to do something similar.
import groovyx.gpars.GParsPool
public class Task {
def compute(int msg) {
String str = "";
long begTest = new java.util.Date().getTime();
System.out.println("start - Task "+ msg);
try {
Thread.sleep(1000);
for(int i = 0; i < 20000; i++)
str = str + 't';
} catch (InterruptedException e) {}
Double secs = new Double((new java.util.Date().getTime() - begTest)*0.001);
System.out.println("run time " + secs + " secs");
return msg;
}
}
final def task = new Task()
def seq = {
println "sequential"
long b = new Date().getTime()
(1..5).each {
task.compute(it)
long e = new Date().getTime()
println e-b
}
}()
println "\nparallel"
GParsPool.withPool { // pool size will be automatically computed (if nothing is specified).
long b = new Date().getTime()
(1..5).eachParallel { // executes each block in parallel and statement within the block sequentially.
task.compute(it)
long e = new Date().getTime()
println e-b
}
}
println "\nasync (demo)"
long start = new Date().getTime()
// Say we have few tasks that needs to be computed asynchronously while doing other computations.
def a = {task.compute(1)} // define the tasks in a block
def b = {task.compute(2)}
def c = {task.compute(3)}
def d = {task.compute(4)}
def e = {task.compute(5)}
def results = GParsPool.withPool {
[a,b,c,d,e]*.callAsync() // perform the tasks in the background
}
// continue with other tasks..
results*.get() // now we need the results to continue further. Get the result (if not done yet, it waits till done).
// do further computation with the obtained results..
long stop = new Date().getTime()
println stop-start
This can be run using groovyConsole
. GPars must be in the classpath or included using grapes. In my test system having dual cores, the time taken are around 10375ms
, 6578ms
, 6234ms
for sequential
, parallel
, and async
tasks respectively. In a single core atom processor the average time for 3 runs are as 13792ms
, 10771ms
and 9078ms
respectively.