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
Postar um comentário