Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parallelize this groovy code?

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
}
like image 644
lucas Avatar asked May 26 '10 16:05

lucas


2 Answers

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.

like image 31
Don Branson Avatar answered Sep 30 '22 14:09

Don Branson


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)
    }
  }

}
like image 119
Christoph Metzendorf Avatar answered Sep 30 '22 16:09

Christoph Metzendorf