From the code example you've provided, I'm not 100% sure what you are trying to accomplish. It appears you are trying to an Actor
for each value within the range provided and react to the message by printing out the value provided.
Given that, your code has some issues. The main issue is the lack of the loop{}
closure, which insures the Actor
waits for the next incoming message after processing one.
Secondly, invoking stop()
doesn't help either. It simply stops the Actor
from receiving additional messages. It doesn't hurt anything in your case, since you immediately call join, but adds to the confusion.
To get this working, here is your code simplified into a working example:
import groovyx.gpars.actor.Actors
def a = 1
def b = 100000
def actor = Actors.actor {
loop {
react {
println it
}
}
}
(a..b).each {
actor << it
}
actor.join()
In this example, for each value in the range, a message is added to the actor, which reacts to the message by printing the value and then, because of the 'loop' closure waits for the next incoming message.
So that example should accomplish what you want. However, to give some clarity into what is going on in your code, here is an explanation.
When your Actor
'reacts' to a message, you are sending a message to a Reactor
. Even though you don't explicitly return a value, in Groovy, the last line within a Closure is the return statement. As a result, since your last line within the Closure is a println
, the return of that is null. So, your Reactor
returns null, which is treated as a message to the Actor
and again processed.
To avoid this scenario, you need to evaluate the return message and only delegate the message / or print it if it has not yet been processed. I have updated your code, intentionally return 'done' as the return message for clarity. You could change the code to just check for a null
message before processing it:
import groovyx.gpars.actor.Actors
def a = 1
def b = 100000
def reactor2 = Actors.reactor { message ->
if(!message.equals("done")) {
println "\t\tReact Again: $message"
}
return "done"
}
def reactor = Actors.reactor { message ->
if(!message.equals("done")) {
println "\tReact: $message"
reactor2 << message
}
return "done"
}
def actor = Actors.actor {
loop {
react {
if(!it.equals("done")) {
println it
reactor << it
}
}
}
}
(a..b).each {
actor << it
// actor.oi
}
actor.join()