2010-05-26 6 views
3

J'essaye d'écrire un composant réutilisable dans Groovy pour tirer facilement des emails de certaines de nos applications Java. Je voudrais passer une liste, où Email est juste un POJO (POGO?) Avec quelques informations par email. Je voudrais qu'il soit multithread, au moins en exécutant toute la logique d'email dans un deuxième fil, ou fais un fil par email.Comment paralléliser ce code groovy?

Je suis vraiment brumeux sur le multithreading en Java, donc ça n'aide probablement pas! Je l'ai essayé quelques différentes façons, mais voici ce que j'ai en ce moment:

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

} 

J'espérais que le sommeil serait au hasard lent certains fils vers le bas de sorte que la sortie de la console ne serait pas séquentiel. Au lieu de cela, je vois ceci:

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 fait essentiellement ce que vous attendez, y compris la déclaration println, et le client qui appelle cette suite,

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 
} 

Répondre

10

Pour vous aider exemple ci-dessus en cours d'exécution en même temps que vous devez remplacer la ligne

threads.each { it.run() } 

avec

threads.each { it.start() } 

comme run() ne démarre pas un nouveau thread et donc votre code en cours d'exécution a été successivement.

Il existe également une extension Groovy disponible appelée GPars. Il supporte plusieurs techniques de simultanéité comme Fork/Join ou le modèle Actor. En utilisant GPars, votre code pourrait être simplifié à ceci:

def sendEmails(emails) { 

    GParsPool.withPool { 
    emails.eachParallel { email -> 
     def wait = (long) new Random().nextDouble() * 1000 
     println "in closure" 
     this.sleep wait 
     sendEmail(email) 
    } 
    } 

} 
2

Deux versions Java arrière (1.5 Ils ont introduit de nouvelles fonctionnalités de simultanéité qui rendent le threading Java encore plus simple. Google pour java ThreadExecutor, et vous trouverez quelques pages telles que:

http://www.deitel.com/articles/java_tutorials/20051126/JavaMultithreading_Tutorial_Part4.html

Que Groovy rend encore plus simple, je ne peux pas dire, mais vous voudrez peut-être appliquer les techniques de Java « nouvelles » à votre Exemple Java d'abord avant de faire la comparaison.

+0

Merci Don, cela aide. J'ai remplacé l'exécution et la jointure avec threadExecutor.execute à la place, puis threadExecutor.shutdown(), et enfin threadExecutor.awaitTermination (1, TimeUnit.MINUTES) car je pense qu'il était prématurément en train de quitter et de tuer les threads générés. On dirait que je suis en train de courir maintenant. – lucas

+0

COOL! Content que cela ait aidé. –