I'm trying to write a reusable component in Groovy to easily shoot off emails from some of our Java applications. I would like to pass it a List, where Email is just a POJO(POGO?) with some email info. I'd like it to be multithreaded, at least running all the email logic in a second thread, or make one thread per email.
I am really foggy on multithreading in Java so that probably doesn't help! I've attempted a few different ways, but here is what I have right now:
void sendEmails(List<Email> emails) {
def threads = []
def sendEm = emails.each{ email ->
def th = new Thread({
Random rand = new Random()
def wait = (long)(rand.nextDouble() * 1000)
println "in closure"
this.sleep wait
sendEmail(email)
})
println "putting thread in list"
threads << th
}
threads.each { it.run() }
threads.each { it.join() }
}
I was hoping the sleep would randomly slow some threads down so the console output wouldn't be sequential. Instead, I see this:
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
putting thread in list
in closure
sending email1
in closure
sending email2
in closure
sending email3
in closure
sending email4
in closure
sending email5
in closure
sending email6
in closure
sending email7
in closure
sending email8
in closure
sending email9
in closure
sending email10
sendEmail basically does what you'd expect, including the println statement, and the client that calls this follows,
void doSomething() {
Mailman emailer = MailmanFactory.getExchangeEmailer()
def to = ["one","two"]
def from = "noreply"
def li = []
def email
(1..10).each {
email = new Email(to,null,from,"email"+it,"hello")
li << email
}
emailer.sendEmails li
}
A couple of Java versions back (1.5) they introduced some new concurrency stuff that makes Java threading (even more) simple. Google for java ThreadExecutor, and you'll find some pages such as:
http://www.deitel.com/articles/java_tutorials/20051126/JavaMultithreading_Tutorial_Part4.html
Whether Groovy makes it even simpler, I can't say, but you might want apply the "new" Java techniques to your Java example first before making the comparison.
To get you example above running concurrently you have to replace the line
threads.each { it.run() }
with
threads.each { it.start() }
as run()
doesn't start a new thread and thus your code was running sequentially.
There's also a Groovy extension available called GPars. It supports several concurrency techniques like Fork/Join or the Actor model. Using GPars, your code could be simplified to this:
def sendEmails(emails) {
GParsPool.withPool {
emails.eachParallel { email ->
def wait = (long) new Random().nextDouble() * 1000
println "in closure"
this.sleep wait
sendEmail(email)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With