11. Párhuzamosság
Ahogy már az elöző fejezetekben is elhangzott Groovy-ban sok mindent úgy lehet kezelni mint a Java-ban. Ez nincs máskép a szálkezeléssel és a párhuzamossággal kapcsolatban sem. Egy kicsit módosítva azt.
Elérhetőek olyan keretrendszerek mint a Gpars, amely segíti a biztonságos párhuzamosságot Groovy illetve Java nyelven.
Thread
import java.util.concurrent.atomic.AtomicInteger
def counter = new AtomicInteger()
synchronized out(message) {
println(message)
}
def th = Thread.start {
for( i in 1..8 ) {
sleep 30
out "thread loop $i"
counter.incrementAndGet()
}
}
for( j in 1..4 ) {
sleep 50
out "main loop $j"
counter.incrementAndGet()
}
th.join()
assert counter.get() == 12
Ennek a kimenete:
thread loop 1
main loop 1
thread loop 2
thread loop 3
main loop 2
thread loop 4
thread loop 5
main loop 3
thread loop 6
main loop 4
thread loop 7
thread loop 8
A java.util.concurrent.Exchanger használata
Az Exchange szinkronizál két szálat egy ponton és azok elemeit kicseréli.
A következő példa a Exchanger osztályt használja. A példában két szál (Thread) van, az egyik megtartja a páros számokat és kicseréli a páratlan számokat a másik szállal. A másik szál pedig hanonlóan jár el a páratlan számok esetén, megtartja a páratlan számokat és párosakat kicseréli. Ez elég kezdetleges algoritmus, mert csak egyenlő számú cserékre alkalmazható. A kódból jól látszik hogy a párhuzamosság terén a Java és Groovy ’összemosható’.
def x = new java.util.concurrent.Exchanger()
def first=1..20, second=21..40, evens, odds
def t1 = Thread.start{ odds = first.collect{ it % 2 != 0 ? it : x.exchange(it) } }
def t2 = Thread.start{ evens = second.collect{ it % 2 == 0 ? it : x.exchange(it) } }
[t1, t2]*.join()
println "evens: $evens"
println "odds: $odds"
Ennek a kimenete:
evens: [2, 22, 4, 24, 6, 26, 8, 28, 10, 30, 12, 32, 14, 34, 16, 36, 18, 38, 20, 40]
odds: [1, 21, 3, 23, 5, 25, 7, 27, 9, 29, 11, 31, 13, 33, 15, 35, 17, 37, 19, 39]