import groovy.transform.*
import groovyx.gpars.actor.*
import groovyx.gpars.group.*
@Immutable class Calculate {}
@Immutable class Work { int start, nrOfElements }
@Immutable class Result { double value }
@Immutable class PiApproximation { double pi ; long duration }
double calculatePiFor( int start, int nrOfElements ) {
((start * nrOfElements)..((start + 1) * nrOfElements - 1)).inject( 0.0 ) { acc, i ->
acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
}
}
def group = new DefaultPGroup()
def listener = group.actor {
loop {
react {
println "Pi approx $it.pi in $it.duration"
terminate()
}
}
}
int nrOfWorkers = 4
int nrOfMessages = 1000
int nrOfElements = 1000
def workers = (1..nrOfWorkers).collect {
group.actor {
loop {
react {
reply new Result( calculatePiFor( it.start, it.nrOfElements ) )
}
}
}
}
double pi = 0.0
int nrOfResults = 0
long start = System.currentTimeMillis()
def master = group.actor {
loop {
react {
switch( it ) {
case Calculate:
nrOfMessages.times { i -> workers[ i % nrOfWorkers ].send( new Work( i, nrOfElements ) ) }
break
case Result:
pi += it.value
if( ++nrOfResults >= nrOfMessages ) {
listener.send( new PiApproximation( pi, System.currentTimeMillis() - start ) )
workers*.terminate()
terminate()
}
break
}
}
}
}
master << new Calculate()
master.join()