Concorrência em Java

As últimas APIs de concorrência do Java tornaram o trabalho de gerenciar a execução das tarefas muito mais fácil, mas existem alguns cuidados a serem observados.

Primeiro, evite utilizar Executor e utilize ExecutorService. O problema é que a primeira interface não possui o método shutdown... o programa simplesmente não irá terminar.

Para criar os executores:

    private ExecutorService exec;
    // ...
    int numProc = Runtime.getRuntime().availableProcessors();
    exec = Executors.newFixedThreadPool(numProc);

A classe que irá permitir o gerenciamento das filas e da lista de jobs é a CompletionService. E apesar de não ser fundamental, eu tenho criado uma lista de pendências para acompanhar a execução dos diversos jobs, dessa forma:

        CompletionService cs = new ExecutorCompletionService(exec);
        List> pendencias = new ArrayList>();

E a criação dos task a serem executadas:

        for (Fasta f : contigs) {
            Result res = new Result();
            ContigClassifyRunnable ccr = new ContigClassifyRunnable(f, seedLength, seedRef, res);
            pendencias.add(cs.submit(ccr, res));
        }

Neste caso, a classe ContigClassifyRunnable implementa Runnable e será chamada pelo objeto de CompletionService quando tiver processador disponível.

E por fim, o bloco que aguarda a execução das tarefas terminarem:

        try {
            Future ff = null;
            while (pendencias.size() > 0) {
                ff = cs.take();  // obtem o proximo resultado ou aguarda ter resultado
                // grava os resultados
                if (ff.get() != null) {
                    result.add(ff.get());
                }
                pendencias.remove(ff);
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(ContigClassify.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(ContigClassify.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            exec.shutdown();
        }

Aqui o passo mais importante é chamado por cs.take() que retorna uma tarefa encerrada ou aguarda o encerramento para devolver o objeto future. e no finally a chamada de shutdown que finaliza o pool de thread executoras.

Comentários

Postagens mais visitadas deste blog

Jellyfish script

Conversão do encode do MariaDB para atender o moodle 3.8

O GBParsy é uma biblioteca para realizar o parser de arquivos GenBank para o Python