Como otimizar a execução de tarefas?
Foi desenvolvido um site de comparação de preços. Quando um usuário consulta o preço de um produto, o preço correspondente é obtido nas plataformas S1 e S2, salvo no banco de dados e devolvido ao usuário
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> f1 = executor.submit(()-> getPriceByS1());
Future<Integer> f2 = executor.submit(()-> getPriceByS2());
Integer price1 = f1.get();
save(price1);
Integer price2 = f2.get();
save(price2);
Se demorar muito para obter a cotação do e-commerce S1, mesmo que demore pouco para obter a cotação do e-commerce S2, a operação de salvar a cotação S2 não pode ser executada primeiro, pois a principal thread está bloqueado na operação f1.get().
Solução um:
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> f1 = executor.submit(()-> getPriceByS1());
Future<Integer> f2 = executor.submit(()-> getPriceByS2());
BlockingQueue<Integer> bq = new LinkedBlockingQueue<>();
bq.put(f1.get());
bq.put(f2.get());
for (int i = 0; i < bq.size(); i++) {
Integer price = bq.take();
save(price);
}
Solução dois:
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletionService<Integer> cs = new ExecutorCompletionService<>(executor);
cs.submit(() -> getPriceByS1());
cs.submit(() -> getPriceByS2());
for (int i = 0; i < 2; i++) {
Integer price = cs.take().get();
save(price);
}
Então, como o CompletionService implementa essa função?
É possível obter funções semelhantes combinando BlockingQueue e Executor?
Cenários de uso do CompletionService
Na anotação da classe CompletionService, os dois cenários de uso de CompletionService são na verdade marcados
chamando vários serviços idênticos ao mesmo tempo para obter o resultado.Quando um dos serviços obtém o resultado, ele retorna e cancela outras tarefas.
Cluster de bifurcação tipo Dubbo
Blogue de referência
[1] Livreto de Simultaneidade Java