Java-Обработка Неблокирующих Вызовов


В моем приложении я использую сторонний API. Это неблокирующий метод, который возвращается немедленно. У меня есть коллекция элементов, над которыми я должен вызвать этот метод.

Теперь моя проблема заключается в том, что я должен найти способ, пока все выполнение метода не будет завершено, и выполнить следующую операцию. Как я могу справиться с этим? Я не могу изменить сторонний API.

Короче говоря, это выглядит так

for(Object object: objects){
 methodA(object); //this is a non-blocking call and returns immediately
}
// here I want to do my next task only after all the methodA calls completed execution
3 2

3 ответа:

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

Так ли это?

EDIT

Как отмечает Кэти Стоун, другая возможность заключается в том, что API может иметь механизм обратного вызова, при котором поток (за API), выполняющий работу, начатую вызовом methodA, "перезванивает" в ваш код. (Там должен быть какой-то другой метод в API, который позволяет зарегистрировать объект обратного вызова.)

Есть и другие возможности ... (некоторые слишком ужасны, чтобы их упоминать)... но все они подразумевают, что APIразработан для поддержки синхронизации с окончанием задач, запущенных methodA.

Как заметил Стивен, это возможно, если у вас есть какой-то способ узнать, что метод завершен. Если у вас есть какой-то обратный вызов или прослушиватель для этого, вы можете использовать что-то вроде Счетного семафора:

final Semaphore block = new Semaphore();

//HERE SOMETHING APPROPRIATE TO YOUR API
myAPI.registerListener(new APIListener(){
  public void methodADone(){
    block.release();
  }
});

int permits = 0;
for(Object object: objects){
 methodA(object); //this is a non-blocking call and returns immediately
 permits++;
}
block.acquire(permits);

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

Как вы определение в methodA() звонок завершен?

Возвращает ли метод какой-либо дескриптор? Или у объекта есть какое-либо свойство, которое должно быть задано вызовом methodA()? Поэтому соберите их и сделайте цикл со сном и проверьте все оставшиеся дескрипторы или свойства объекта, каждый из которых удаляется из оставшихся, если он завершен.

Код ожидания может выглядеть следующим образом:

while(!remaining.isEmpty()) {
  try {
    Thread.sleep(100);
  } catch (InterruptedException e) {
    continue;
  }
  Iterator<HandleOrObjectWithProperty> i = remaining.iterator();
  while (i.hasNext()) {
    HandleOrObjectWithProperty result = i.next();
    if (result.handleHasFinishedOrPropertyIsSet()) {
      i.remove();
    }
  }
}