Groovy #7: Paralelizando as coisas

Tempo de leitura: menos de 1 minuto

paralelismoFala galera, tudo certo?

Esses dias chegou um chamado de uma empresa para eu atender. No chamado o usuário relatava que ao fazer a integração de dados do sistema origem para o nosso sistema, eram eventualmente geradas criticas de validação incorretamente, críticas que não condiz ao verdadeiro estado do registro.

Deu um puta trabalham entender o que estava acontecendo, para encurtar o “causo”, o problema ocorria devido a paralelismo utilizado processo de integração de dados. Este usava um utilitário que mantinha por um curto espaço de tempo estado em seus atributos internos, fazendo com que uma thread usa-se dados de outra thread, causando assim o problema.

Nota: Ao usar paralelismo, tome muito cuidado com objetos estáticos ou singleton que mantem estados sem seus atributos, isso pode te dar uma bela dor de cabeça.

Dado o inusitado fato, tivemos a necessidade de se criar um teste para garantir que isso não mais iria ocorrer. Mas como simular várias threads executando o mesmo código ao mesmo tempo?

É para responder essas e outras perguntas que o GPars Framework foi criado.

GPars é uma biblioteca de código aberto para Java e Groovy para resolver problemas de concorrência e paralelismo e lhe dá uma série de abstrações de alto nível para escrever código simultâneo e paralelo (map/reduce, fork/join, asynchronous closures, actors, agents, dataflow concurrency and other concepts).

Já usamos o GPars em outras partes do sistema, aproveitando isso, também usei-o no teste.

Meu teste ficou assim:

[code language=”java”]
@Test
public void CFOP_test_dominio_cfop_concorrentencia_entre_threads() throws Exception {
RegrasUtilSfw.buscarCfopNaTabelaDominioNaDataAtual(‘5101’)
try {
GParsExecutorsPool.withPool { pool ->
[‘5101’, ‘5201’, ‘6101’, ‘6201’].eachParallel {
for (int i = 0; i < 10000; i++) {
final Cfop cfop = RegrasUtilSfw.buscarCfopNaTabelaDominioNaDataAtual(it);
Assert.assertEquals(it +" —-> "+cfop.toString(), it, cfop.getCodigo());
}
}
}
} catch (final AsyncException e) {
throw new SistemaException(e.getConcurrentExceptions().get(0))
}
}
[/code]

Na linha 5, através do GPars, criei um poll de execuções. Na linha 6, pedi para o GPars executar cada um dos códigos CFOPs da lista ([‘5101’, ‘5201’, ‘6101’, ‘6201’]) em paralelo, aqui foram criados 4 threads, uma para cada código, fazendo o loop dez mil vez, caso o código fosse diferente do esperado pelo menos uma vez o teste falha.

Nas linhas 13 e 14, foi acionado uma catch, para pegar eventuais exceções lançadas em uma das threads.

E isso é tudo pessoal. Vemos no exemplo a cima que é muito simples usar o GPars que executar coisas em paralelo, estão aproveite e use!

Aproveitando, não deixe de participar do CodeKata #6: Conversão numérica, já tem gente desenvolvendo e “esmerilando o código” para deixa-lo performático. Não fique fora dessa!

Abraços.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *