Java ScheduledFuture выполняет асинхронную задачу, дождитесь завершения

Чтобы асинхронно отправлять большие электронные письма с фиксированной скоростью, я использую ScheduledExecutorService.

У меня есть класс, реализующий Runnable, который асинхронно отправляет почту. Его нужно вызывать каждую секунду и ровно x раз. Для фактической отправки я использую Простая почта Java. Я вызываю метод EmailBuilder#send(mail, /* boolean async */ true).

После того, как этот метод был вызван эти x раз, вызывается ScheduledExecutorService#shutdown().

Я бы хотел определить, в какой момент времени все запланированные Runnables завершились, то есть все вызовы EmailBuilder#send(mail, /* boolean async */ true) вернулись.

Я попробовал ScheduledExecutorService#awaitTermination() с некоторым таймаутом, а также ScheduledFuture#get(), но это не сработало или возникло какое-то исключение.

package playground;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.simplejavamail.email.Email;
import org.simplejavamail.email.EmailBuilder;
import org.simplejavamail.mailer.Mailer;
import org.simplejavamail.mailer.MailerBuilder;

public class MCVE {

    private ScheduledExecutorService scheduler;
    private SendTask sd;
    private ScheduledFuture<?> sf;
    private boolean terminateFlag = false;

    public void start() {
        sd = new SendTask();
        scheduler = Executors.newSingleThreadScheduledExecutor();
        sf = scheduler.scheduleAtFixedRate(sd, 0, 1, TimeUnit.SECONDS);
    }

    private class SendTask implements Runnable {

        @Override
        public void run() {
            Mailer mailer = MailerBuilder.withSMTPServer("smtp.gogglemail.com", 587).buildMailer();

            Email mail = EmailBuilder.startingBlank()
                .from("[email protected]")
                .to("[email protected]")
                .withSubject("Subject")
                .withPlainText("Content")
                .buildEmail();

            mailer.sendMail(mail, /* async */ true);

            if (terminateFlag) {
                sf.cancel(true);
                scheduler.shutdown();
                return;
            }
        }
    }

}

Спасибо за полезный совет!

Вам действительно нужно добавить код, желательно минимальный воспроизводимый пример.

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

Ответы 2

Соберите все фьючерсы, возвращенные после планирования, в коллекции, а затем выполните foreach get ().

ScheduledExecutorService#scheduleAtFixedRate() возвращает только один ScheduledFuture. Вызов get() бросает CancellationException.
Jakob Benz 23.10.2018 17:23

Если вы планируете с фиксированной скоростью, когда вы ожидаете, что все задачи будут выполнены ?, это будет повторяться вечность.

Eddie Jamsession 24.10.2018 10:08

Нет, поскольку ScheduledExecutorService выключен, выполнение программы будет прекращено.

Jakob Benz 24.10.2018 19:17

А как насчет sf.isCancelled ()? Это не то, что вы ищете?

Нет, потому что ScheduledFuture#cancel() вызывается после начала отправки всех писем, но поскольку они отправляются асинхронно, неясно, действительно ли процесс отправки завершен. Таким образом, ScheduledFuture#isCancelled() вернет true до того, как все письма будут отправлены (полностью), если отправка занимает больше времени, чем период / скорость, переданные ScheduledExecutorService#scheduleAtFixedRate().

Jakob Benz 23.10.2018 17:45

Ваш SendTask уже асинхронно вызван из вашей основной программы. Почему вы вызываете async почтовой программы, а затем хотите узнать, когда она завершится? Вы можете выполнить синхронизацию этого вызова, удалить завершенную часть и использовать метод, предложенный @Eddie.

Vasif 23.10.2018 17:59

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