For Beginners
     A Groovy approach to concurrent programming




Matt Passell                               May 25, 2011
About Me
•   Longtime Java developer (since '97)
•   Using Groovy on and off since early 2008
•   Concurrent programming enthusiast
•   Started software consultancy in 2007
•   More Groovy + Less Java = More Happy
Early History
●
  October 2008: Václav Pech creates
  GParallelizer
●
  September 2009: project renamed
  to GPars, moved to Codehaus, and
  Groovy luminaries join the team -
    (Dierk König, Paul King, Alex Tkachman, Russel
    Winder)
GPars Has a Logo Contest




    http://gpars.codehaus.org/Logo+Contest
History
●
    October 2008: Václav Pech creates GParallelizer
●
    September 2009: project renamed to GPars,
    moved to Codehaus, and Groovy luminaries join
    the team (Dierk König, Paul King, Alex Tkachman, Russel Winder)
●
    December 2009: GPars gets a logo
●
    May 2010: 0.10 Release
●
    December 2010: 0.11 Release
●
    May 2011: 0.12 Beta 1
What GPars Provides
●
    Code-level Helpers
●
    Architecture-level Concepts
●
    Protecting Shared Mutable State
What GPars Provides
●
    Code-level Helpers
    ●
        Fork/Join
    ●
        Map/Reduce (Parallel Collections)
    ●
        Asynchronous Processing*




              *not covered in this presentation
What GPars Provides
●
    Architecture-level Concepts
    ●
        Dataflow Concurrency
    ●
        Actors
    ●
        Communicating Sequential Processes*




                 *not covered in this presentation
What GPars Provides
●
    Protecting Shared Mutable State
    ●
        Agents
    ●
        Software Transactional Memory*




             *not covered in this presentation
Recurring Patterns
●
    Favor immutability
●
    Stateless code blocks (similar to
    Servlets)
Fork/Join & Map/Reduce

    Fork   Join         Fork     Join




     Map          Map          Reduce
Fork/Join
def list = [1, 2, 3, 4]
GParsPool.withPool {
    assert [2, 4, 6, 8] == list.collectParallel { it * 2 }
    def animals = ['dog', 'ant', 'cat', 'whale']
    println(animals.makeTransparent().
      collect {it.toUpperCase()}.
      groupBy {it.contains 'A'})
}


ParallelEnhancer.enhanceInstance(list)
assert [2, 4, 6, 8] == list.collectParallel { it * 2 }




                            DemoParallelizer & DemoParallelEnhancer.groovy
Fork/Join
def list = [1, 2, 3, 4]
GParsPool.withPool {
    assert [2, 4, 6, 8] == list.collectParallel { it * 2 }
    def animals = ['dog', 'ant', 'cat', 'whale']
    println(animals.makeTransparent().
      collect {it.toUpperCase()}.
      groupBy {it.contains 'A'})
}


ParallelEnhancer.enhanceInstance(list)
assert [2, 4, 6, 8] == list.collectParallel { it * 2 }




                            DemoParallelizer & DemoParallelEnhancer.groovy
Parallel Collections (Map/Reduce)
GParsPool.withPool {
     assert 20 == [1, 2, 3, 4, 5].parallel.
      filter {it % 2 == 0}.
      map {it ** 2}.
      reduce {a, b -> a + b} //sum the squares of even numbers


     def urls = ['http://www.jroller.com', 'http://www.dzone.com',
                'http://www.infoq.com']
     println 'Sum of chars in all pages: ' +
      urls.parallel.map { it.toURL().text.size() }.sum()


//The equivalent using Fork/Join
//    println urls.collectParallel { it.toURL().text.size() }.sum()
}



                                                      DemoMapReduce.groovy
Dataflow Concurrency
●
    Modeled as a flow of data rather
    than a flow of execution
●
    Tree of dependent values
Like this?
How about this?
My Last Try
              A




    B                 C




D         E       D
When you put it that way...
             A




      B              C




E                D
In Code
def flow = new DataFlows()
task { flow.a = flow.b + flow.c }
task { flow.b = flow.d + flow.e }
task { flow.c = flow.d }
task { flow.d = 17 }
task { flow.e = 12 }
assert 46 == flow.a
println "flow.a = ${flow.a}"
println "flow.b = ${flow.b}"
Actors
final def doubler = Actors.reactor {
    2 * it
}

Actor actor = Actors.actor {
    (1..10).each {doubler << it}
    int i = 0
    loop {
        i += 1
        if (i > 10) stop()
        else {
            react {message ->
                println "Double of $i = $message"
            }
        }
    }
}

actor.join()
doubler.stop()
doubler.join()



                                               DemoReactor2.groovy
Actors
final def doubler = Actors.reactor {
    2 * it
}

Actor actor = Actors.actor {
    (1..10).each {doubler << it}
    int i = 0
    loop {
        i += 1
        if (i > 10) stop()
        else {
            react {message ->
                println "Double of $i = $message"
            }
        }
    }
}

actor.join()
doubler.stop()
doubler.join()



                                               DemoReactor2.groovy
Agents
def jugMembers = new Agent<List<String>>(['Me']) //add Me

jugMembers.send {it.add 'James'} //add James


//add Joe using the left-shift operator
final Thread t1 = Thread.start { jugMembers << { it.add 'Joe' } }

final Thread t2 = Thread.start {
    jugMembers {it.add 'Dave'} //use the implicit call() method
    jugMembers {it.add 'Alice'} //use the implicit call() method
}


[t1, t2]*.join()
println jugMembers.val
jugMembers.valAsync {println "Current members: $it"}
jugMembers.await()

                                                            DemoAgent.groovy
Resources
●
    ReGinA Chapter 17 -
    http://manning.com/koenig2/
●
    GPars User Guide -
    http://gpars.org/0.11/guide/index.html
●
    GPars User Mailing List -
    http://xircles.codehaus.org/lists/user@gpars.codehaus.org
●
    Dierk König's presentation (Concurrent programming for you and me) -
    http://skillsmatter.com/podcast/groovy-grails/concurrent-programming-for-you-and-me

●
    Alex Miller's DevWorks article -
    http://www.ibm.com/developerworks/java/library/j-gpars/index.html
●
    Václav Pech's blog -
    http://www.jroller.com/vaclav/
Credits
●
    GPars logo contest entries: various, late 2009. Author: various -
    http://gpars.codehaus.org/Logo+Contest
●
    Giant Fork: A metal four-pronged fork, Jun 2010. Author: dismal_denizen -
    http://www.openclipart.org/detail/65749
●
    Tree image: Linde von Linn, Jun 2006. Author: Stefan Wernli -
    http://commons.wikimedia.org/wiki/File:Linde_von_linn.jpg
●
    George Clooney image: Nov 2006. Author: James White/Corbis Outline -
    http://bit.ly/iCSVal
●
    Meryl Streep image: 2009. Author: unknown -
    http://gosublogger.com/wp-content/uploads/2009/02/meryl-streep.jpg
Q&A


    http://bit.ly/gparsboston
mpassell@grovehillsoftware.com
http://blog.grovehillsoftware.com
        @softwaregrove

GPars For Beginners

  • 1.
    For Beginners A Groovy approach to concurrent programming Matt Passell May 25, 2011
  • 2.
    About Me • Longtime Java developer (since '97) • Using Groovy on and off since early 2008 • Concurrent programming enthusiast • Started software consultancy in 2007 • More Groovy + Less Java = More Happy
  • 3.
    Early History ● October 2008: Václav Pech creates GParallelizer ● September 2009: project renamed to GPars, moved to Codehaus, and Groovy luminaries join the team - (Dierk König, Paul King, Alex Tkachman, Russel Winder)
  • 4.
    GPars Has aLogo Contest http://gpars.codehaus.org/Logo+Contest
  • 5.
    History ● October 2008: Václav Pech creates GParallelizer ● September 2009: project renamed to GPars, moved to Codehaus, and Groovy luminaries join the team (Dierk König, Paul King, Alex Tkachman, Russel Winder) ● December 2009: GPars gets a logo ● May 2010: 0.10 Release ● December 2010: 0.11 Release ● May 2011: 0.12 Beta 1
  • 6.
    What GPars Provides ● Code-level Helpers ● Architecture-level Concepts ● Protecting Shared Mutable State
  • 7.
    What GPars Provides ● Code-level Helpers ● Fork/Join ● Map/Reduce (Parallel Collections) ● Asynchronous Processing* *not covered in this presentation
  • 8.
    What GPars Provides ● Architecture-level Concepts ● Dataflow Concurrency ● Actors ● Communicating Sequential Processes* *not covered in this presentation
  • 9.
    What GPars Provides ● Protecting Shared Mutable State ● Agents ● Software Transactional Memory* *not covered in this presentation
  • 10.
    Recurring Patterns ● Favor immutability ● Stateless code blocks (similar to Servlets)
  • 11.
    Fork/Join & Map/Reduce Fork Join Fork Join Map Map Reduce
  • 12.
    Fork/Join def list =[1, 2, 3, 4] GParsPool.withPool { assert [2, 4, 6, 8] == list.collectParallel { it * 2 } def animals = ['dog', 'ant', 'cat', 'whale'] println(animals.makeTransparent(). collect {it.toUpperCase()}. groupBy {it.contains 'A'}) } ParallelEnhancer.enhanceInstance(list) assert [2, 4, 6, 8] == list.collectParallel { it * 2 } DemoParallelizer & DemoParallelEnhancer.groovy
  • 13.
    Fork/Join def list =[1, 2, 3, 4] GParsPool.withPool { assert [2, 4, 6, 8] == list.collectParallel { it * 2 } def animals = ['dog', 'ant', 'cat', 'whale'] println(animals.makeTransparent(). collect {it.toUpperCase()}. groupBy {it.contains 'A'}) } ParallelEnhancer.enhanceInstance(list) assert [2, 4, 6, 8] == list.collectParallel { it * 2 } DemoParallelizer & DemoParallelEnhancer.groovy
  • 14.
    Parallel Collections (Map/Reduce) GParsPool.withPool{ assert 20 == [1, 2, 3, 4, 5].parallel. filter {it % 2 == 0}. map {it ** 2}. reduce {a, b -> a + b} //sum the squares of even numbers def urls = ['http://www.jroller.com', 'http://www.dzone.com', 'http://www.infoq.com'] println 'Sum of chars in all pages: ' + urls.parallel.map { it.toURL().text.size() }.sum() //The equivalent using Fork/Join // println urls.collectParallel { it.toURL().text.size() }.sum() } DemoMapReduce.groovy
  • 15.
    Dataflow Concurrency ● Modeled as a flow of data rather than a flow of execution ● Tree of dependent values
  • 16.
  • 17.
  • 18.
    My Last Try A B C D E D
  • 19.
    When you putit that way... A B C E D
  • 20.
    In Code def flow= new DataFlows() task { flow.a = flow.b + flow.c } task { flow.b = flow.d + flow.e } task { flow.c = flow.d } task { flow.d = 17 } task { flow.e = 12 } assert 46 == flow.a println "flow.a = ${flow.a}" println "flow.b = ${flow.b}"
  • 21.
    Actors final def doubler= Actors.reactor { 2 * it } Actor actor = Actors.actor { (1..10).each {doubler << it} int i = 0 loop { i += 1 if (i > 10) stop() else { react {message -> println "Double of $i = $message" } } } } actor.join() doubler.stop() doubler.join() DemoReactor2.groovy
  • 22.
    Actors final def doubler= Actors.reactor { 2 * it } Actor actor = Actors.actor { (1..10).each {doubler << it} int i = 0 loop { i += 1 if (i > 10) stop() else { react {message -> println "Double of $i = $message" } } } } actor.join() doubler.stop() doubler.join() DemoReactor2.groovy
  • 23.
    Agents def jugMembers =new Agent<List<String>>(['Me']) //add Me jugMembers.send {it.add 'James'} //add James //add Joe using the left-shift operator final Thread t1 = Thread.start { jugMembers << { it.add 'Joe' } } final Thread t2 = Thread.start { jugMembers {it.add 'Dave'} //use the implicit call() method jugMembers {it.add 'Alice'} //use the implicit call() method } [t1, t2]*.join() println jugMembers.val jugMembers.valAsync {println "Current members: $it"} jugMembers.await() DemoAgent.groovy
  • 24.
    Resources ● ReGinA Chapter 17 - http://manning.com/koenig2/ ● GPars User Guide - http://gpars.org/0.11/guide/index.html ● GPars User Mailing List - http://xircles.codehaus.org/lists/user@gpars.codehaus.org ● Dierk König's presentation (Concurrent programming for you and me) - http://skillsmatter.com/podcast/groovy-grails/concurrent-programming-for-you-and-me ● Alex Miller's DevWorks article - http://www.ibm.com/developerworks/java/library/j-gpars/index.html ● Václav Pech's blog - http://www.jroller.com/vaclav/
  • 25.
    Credits ● GPars logo contest entries: various, late 2009. Author: various - http://gpars.codehaus.org/Logo+Contest ● Giant Fork: A metal four-pronged fork, Jun 2010. Author: dismal_denizen - http://www.openclipart.org/detail/65749 ● Tree image: Linde von Linn, Jun 2006. Author: Stefan Wernli - http://commons.wikimedia.org/wiki/File:Linde_von_linn.jpg ● George Clooney image: Nov 2006. Author: James White/Corbis Outline - http://bit.ly/iCSVal ● Meryl Streep image: 2009. Author: unknown - http://gosublogger.com/wp-content/uploads/2009/02/meryl-streep.jpg
  • 26.
    Q&A http://bit.ly/gparsboston mpassell@grovehillsoftware.com http://blog.grovehillsoftware.com @softwaregrove