Boa tarde,
Tenho uma aplicação que necessitará consultar algumas informações no banco de dados. São umas 12 consultas que serão disparadas.
Porém esse banco é muito lento e algumas vezes esse processo demora até 1 minuto para ser concluído. O tempo desejado seria em torno de 15 segundos.
Para resolver essa questão, optei em criar algumas threads para que as consultas fosse processadas paralelamente e ao final, os resultados seriam atribuídos em um objeto.
Nunca tive a necessidade de implementar algo assim e andei fazendo alguns estudos para verificar a melhor maneiro.
Criei um exemplo para que alguém pudesse me informar se o caminho está correto ou errado.
Segue abaixo o exemplo.
Classe que processar as Threads.
Os valores retornados são calculados gerando um resultado.
public class Teste {
public static void main(String[] args) {
try {
long inicio = System.currentTimeMillis();
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> resultado1 = executor.submit(new Teste1());
Future<Double> resultado2 = executor.submit(new Teste20());
System.out.println(resultado1.get() * resultado2.get());
long fim = System.currentTimeMillis();
executor.shutdown();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Classe que retorna um inteiro.
public class TesteCalcInteiro implements Callable<Integer> {
public TesteCalcInteiro() {
}
@Override
public Integer call() throws Exception {
try {
Thread.sleep(10000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return 2;
}
}
Classe que retorna um double
public class TesteCalcDouble implements Callable<Double> {
public TesteCalcDouble() {
}
@Override
public Double call() throws Exception {
try {
Thread.sleep(10000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return 2.5;
}
}
Para facilitar a analise do resultado, coloquei uma thread para que ela dormisse durante 10 segundos. Isso facilitou muito para que eu tivesse uma idéia de o quanto rápido ficou.
Espero que eu tenha sido claro na explicação e fico muito grato se alguém puder me ajudar com essa questão pois a minha necessidade primordial no momento é fazer com que a aplicação funcione o mais rápido possivel.
Att,
Marco
É isso mesmo. Verifique se seu banco permite que mais de uma thread acesse a mesma conexão; provavelmente não, então você terá de usar uma conexão para cada thread. Use um pool de conexões para evitar afogar seu banco com excesso de conexões abertas.
Boa tarde entanglement,
No banco eu criei um pool de conexão justamente para evitar qualquer demorar no processamento.
Mesmo assim, achei q não consegui obter bons resultados. O grande problema é que o banco é horrível. E utilizando o JMeter para fazer alguns testes com aplicação usando thread e sem thread percebi que em alguns momentos a que não possuí thread é mais rápida. Mas é complicado assumir esses resultados porque o banco não ajuda em nada. Se voce tiver algum sugestão que possa resolver isso séria uma otima.
Abs.
O banco é horrível ou está faltando (ou sobrando) índices adequados para as consultas que você precisa fazer?
Consultas com “LIKE” são normalmente venenosas. Veja se alguma das consultas tem um “table scan”. Se ela tiver, não adianta ficar paralelizando consultas porque provavelmente as consultas estão demorando devido a I/O, não a CPU do banco.
Infelizmente o banco é péssimo mesmo.O pior é que não existe nada que possamos fazer para melhorar.
É um banco AS/400 que fica em outro pais. Quando ocorre algum problema nele, temos que acionar o cliente para ele abrir uma solicitação lá fora para que o problema seja resolvido.
Nem nos nem o cliente podemos resolver nenhum problema. Tem que esperar uma solução.
Mas voce teria algum sugestão relacionada a Thread que eu possa utilizar para melhorar algum ponto ?
Abs
O que o entanglement disse está certo. Se do tempo total de processamento o que demora mais é a consulta ao banco, não há muito o que fazer na aplicação, pois à partir do momento que a consulta é “disparada” seu programa não pode fazer muito além de esperar que o banco a execute. Acho que você poderia primeiro medir o tempo total de processamento e depois medir o tempo apenas das chamadas que o código faz à base de dados, para saber a porcentagem do tempo total de processamento que é gasta pelo banco e não pela sua aplicação.
Uma coisa que eu pensei é se de fato estas suas consultas precisam ser on-line… Dependendo do caso é possível criar um cache na sua app e ir na base somente quando o valor não está no cache. Mas aí depende da aplicação, nem sempre isso é possível.
Só como exemplo do que estou falando, teve uma vez quando eu trabalhava em uma seguradora que a parte do cálculo precisava de vários índices que ficavam na base de dados. Quando tinham muitos usuários ficava lento o cálculo devido a estas pesquisad nestes índices. Quando eu fui ver com o pessoal que atualizava esses índices, eu descobri que isso era feito através de um “job” deles apenas algumas vezes na semana. À partir disso, fizemos uma implementação na qual quando o job deles terminava ele disparava um processo que fizemos que atualizava estes índices no cache que criamos, então na nossa aplicação estes índices passaram a ser consultados diretamente nesse cache e não na base de dados. Isso acelerou bem o tempo de processamento, mas como disse foi possível apenas porque estes dados eram atualizados poucas vezes durante a semana, então depende do caso mesmo.
rogeriopaguilar,
Entendi as soluções mas como o banco não fica no brasil, fica em outro pais não tenho muito a fazer.
Nem mesmo o cliente consegue fazer nada quando ocorre algum lentidão ou indisponibilidade. A solução é sempre esperar.
Em relação ao cache, sempre gostei dessa solução, Porém, as informações são dados de cliente que desejam informações sobre o produto comercializado. Não tenho como fazer um cache pois nem são informações que são alteradas constantemente por um sistema e nem tenho como prever quais informações e de quais clientes eu poderia alocar em memória. Esse banco possui uma base gigantesca.
Pretendo comentar as chamadas no banco para conseguir medir o custo de processamento sem o acesso ao dados. Acredito que devo ter algum ganho.
A Thread foi uma solução que encontrei para que todas as consultas fossem executadas ao mesmo tempo sem a necessidade de aguardar uma determinada consulta terminar para iniciar uma próxima.
Mas independente disso, haverá uma certa demora devido ao tempo de execução das consultas.
Abs