2015-01-24 3 views
1

У меня есть процесс, который представляет несколько задач в ExecutorService, например MyTask. Моя задача запрашивает значение из внешней службы, например ExternalService. То, что я пытаюсь сделать, это то, что для ExternalService в пакетном процессе запросы, говорят, каждый 100 входящий или 1 раз в секунду, и до этого времени, чтобы нити MyTask быть отложено, пока они не получат ответ:Несколько потоков ждут пакетной работы

public class MyTask implements Runnable { 

    @Override 
    public void run() { 
     try { 
      // .... code .... 


      ExternalData data = externalService.getData(id); 

      // ..... code after batch ... 

     }catch (Exception e){ 

     } 
    } 
} 

Мне нужно обслуживание externalService положить на удержание MyTask до тех пор, пока он не выполнит свою работу в пакетном режиме (путем накопления 100 запросов или ожидания в течение 1 сек.) И верните результат для продолжения задачи.

Каков наилучший способ решения этой проблемы?

Спасибо

ответ

1

Это может быть достигнуто с помощью CyclicBarrier.

CyclicBarriers полезны в программах, включающих фиксированную партию нитей, которые иногда должны ждать друг друга.

Создать барьер, к которому может обратиться вся задача. Аргументы количество задач, которые вы хотите, чтобы ждать, когда вызов await() и действия выполнить после ожидания:

CyclicBarrier barrier = new CyclicBarrier(100, action); 

Каждых задачи должны вызывать await. Это будет ждать, пока в общей сложности 100 задач не достигли этой точки или до 1 секунды:

barrier.await(1, TimeUnit.SECONDS); 

В случае тайм-аута, запустите action в любом случае. action - это runnable, который вызывает внешнюю службу. Поскольку action работает одновременно, вам, вероятно, также нужно будет заставить ваши задачи ждать, пока он завершит работу и получит результаты.


Чтобы получить фактические результаты внешней службы, я бы, вероятно, использовал бы что-то вроде следующего. В основном сохраните идентификатор в списке и заблокируйте его до тех пор, пока результат не будет готов.

action.addId(id); 
barrier.await(...); // run batch action using all IDs 
result = action.getResult(id); // blocks until result is ready 
+0

Это прекрасная функция, о которой я не знал, поэтому, если мой externalservice - это действие, которое я передаю циклическому барьеру, как все потоки будут принимать результат выполнения и продолжить? у каждого будет другой идентификатор, Еще раз спасибо – tbo

+0

@tbo Действие будет оберткой вокруг вашей службы, которая также обрабатывает идентификаторы и ответ. Я добавил пример. Я думаю, что этот подход должен работать в основном, но я уверен, что он все еще не хватает некоторых вещей, а также требует тщательной обработки ошибок. – Kapep

+0

На этом этапе я думаю, что этот подход действительно близок к тому, что я пытаюсь сделать, я бы предпочел не выполнять мой код на catch, так как если будет достигнут срок ожидания, генерируется TimeoutException и действие не выполняется, а другие потоки получаются исключение breakBarrier, сказав, что я должен поймать исключения и действовать соответственно для достижения моего сценария – tbo

Смежные вопросы