2017-02-01 18 views
0


Я разрабатываю API. Для получения результата этот API должен выполнить 2 запроса БД.
Я попытался следующие стратегии:
Элегантный способ запуска параллельных потоков весной 4

  • Используется вызываемым в качестве типа возвращаемого значения в контроллере.
  • Создал 2 темы в службе (используйте Callable and CoundownLatch), чтобы запустить 2 запроса параллельно и определить время окончания.

    public class PetService { 
        public Object getData() { 
         CountDownLatch latch = new CountDownLatch(2); 
         AsyncQueryDBTask<Integer> firstQuery= new AsyncQueryDBTask<>(latch); 
         AsyncQueryDBTask<Integer> secondQuery= new AsyncQueryDBTask<>(latch); 
         latch.await(); 
    } 
    
    public class AsyncQueryDBTask<T> implements Callable { 
    
        private CountDownLatch latch; 
    
        public AsyncQueryDBTask(CountDownLatch latch) { this.latch = latch;} 
    
        @Override 
        public T call() throws Exception { 
        //Run query 
        latch.countDown(); 
        } 
    

Он работал хорошо, но я чувствую, что я разорвать структуру весной где-то.

Интересно, что это наиболее эффективный способ получить данные весной 4.
-Как знать и 2 потоков, которые работают собственный запрос завершили свою работу?
-Как контролировать поток ресурсов, таких как использование и выпуск потока?

Заранее спасибо.

+1

https://www.mkyong.com/spring/spring-and-java-thread-example/ – StanislavL

ответ

4

Как правило, вы не хотите создавать свои собственные потоки в ApplicationServer или управлять жизненными циклами потоков. На серверах приложений вы можете отправлять задания на ExecutorService, чтобы объединить потоки рабочего потока.

Удобно, весна имеет аннотацию @Async, которая обрабатывает все это для вас. В вашем примере, вы можете создать 2 метод асинхронных, которые возвращают будущее:

public class PetService { 
    public Object getData() { 
     Future<Integer> futureFirstResult = runFirstQuery(); 
     Future<Integer> futureSecondResult = runSecondQuery(); 

     Integer firstResult = futureFirstResult.get(); 
     Integer secondResult = futureSecondResult.get(); 
    } 

    @Async 
    public Future<Integer> runFirstQuery() { 
     //do query 
     return new AsyncResult<>(result); 
    } 

    @Async 
    public Future<Integer> runSecondQuery() { 
     //do query 
     return new AsyncResult<>(result); 
    } 
} 

Пока вы настраиваете ThreadPoolTaskExecutor и включить методы асинхронных, Spring будет обрабатывать представление задач для вас.

ПРИМЕЧАНИЕ. Метод get() блокирует текущий поток до тех пор, пока рабочий поток не возвратит результат, но не заблокирует другие рабочие потоки. Обычно рекомендуется помещать тайм-аут, чтобы предотвратить блокировку навсегда.

+0

Спасибо за ваш ответ. Это действительно полезно. Пожалуйста, помогите мне еще один вопрос. Это нормально: '' 'java Список l = новый ArrayList(); l.add (future1.get()); l.add (future2.get()); '' ' – duy

+0

Да, это нормально. Вызов get возвращает значение в будущем всегда (или генерирует исключение, если вы используете версию тайм-аута) –

+0

Большое спасибо. – duy