Асинхронный вызов в Callable

Рассмотрим следующий код Java (упрощенная версия того, с чем я работаю - если есть ошибки, это потому, что я не запускал его через компилятор):

CountdownLatch latch = new CountdownLatch(collection.size());

for(Whatever thing : collection){

    provider.doWork(thing, result -> {
        process(result);
        latch.countDown();
    };
}

try {
    latch.await();
} catch (InterruptedException ignore) {}

doMoreWork();

Поэтому я запускаю несколько асинхронных задач и жду, пока они все будут выполнены, прежде чем продолжить. Прямо сейчас я накапливаю результат асинхронных задач в списке. Это работает, и это нормально, но я смотрю, есть ли более чистая реализация с использованием Futures или чего-то подобного. Проблема в асинхронном вызове. Callable должен возвращать результат своей работы, но результат этой работы будет известен позже. Переписывать doWork на синхронность не стоит. Должен ли я просто оставить это в покое или есть вариант? Отчасти меня интересует лучший код, а отчасти я просто больше узнаю о параметрах параллелизма. Если это важно, это в приложении для Android.

Можете ли вы попробовать с помощью объекта completableFuture с методом supplyAsync. Это концепция Java 8, которая поможет вам решить вашу задачу.

GauravRai1512 27.10.2018 19:25

Спасибо, читаю это сейчас. Если кто-то захочет предоставить какой-нибудь код, использующий этот класс, это будет приветствоваться.

nasch 27.10.2018 19:35

К сожалению, supplyAsync доступен только в Android API уровня 24, и я не могу установить такой высокий минимальный уровень SDK - слишком много пользователей останется позади.

nasch 27.10.2018 20:21

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

Matthias247 27.10.2018 22:30

Блокировать - нормально, это в фоновом потоке. Спасибо за ваш вклад.

nasch 28.10.2018 03:54
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
550
1

Ответы 1

Это подход с использованием ExecutorService и Future, не тестировался на Android, но все они доступны на уровне 1 api:

ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<String>> pending = new ArrayList<Future<String>>();
for(Whatever thing : collection) {
    Future<String> future = executor.submit(new Callable<String>() {
        public String call() throws Exception {
            return doWork();
        }
    });
    pending.add(future);
}
for (Future<String> result : pending) {
    System.out.println("Your result ASAP:" + result.get());
}
executor.shutdown();

Он вернется, как только текущий элемент будет выполнен, в том порядке, в котором они были отправлены.

Другие вопросы по теме

Я пытаюсь получить идентификатор электронной почты пользователей из базы данных firebase в реальном времени. Но всякий раз, когда я запускаю этот фрагмент кода. он продолжает рушиться
Можно ли заставить новый класс ImageDecoder возвращать растровые изображения, один кадр за другим, вручную?
Поделиться изображением просмотра изображения с намерением в Kotlin
Сбой приложения при загрузке карты: текстуры с размерами 16x256 больше максимального поддерживаемого размера 0x0 в android studio
Firebase Android выключен
Вызвано: java.lang.ClassNotFoundException: не удалось найти класс com.google.android.gms.common.internal.zzbq
Двусторонняя привязка Android при редактировании текста
FindViewById () из другого макета не обновляет данные
Java.lang.NullPointerException: попытка вызвать виртуальный метод void android.widget.ImageView.setImageResource (int) для ссылки на нулевой объект
Добавление кнопки материала в XML приводит к сбою приложения