【问题标题】:Java ScheduledFuture executing asynchronous task wait until completedJava ScheduledFuture 执行异步任务等到完成
【发布时间】:2018-10-23 14:48:27
【问题描述】:

为了以固定速率异步发送大型电子邮件,我使用ScheduledExecutorService

我有一个实现Runnable 的类,它异步发送邮件。它需要每秒被调用一次,并且恰好 x 次。对于实际发送,我使用Simple Java Mail。我调用的方法是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("from@gmail.com")
                .to("to@gmail.com")
                .withSubject("Subject")
                .withPlainText("Content")
                .buildEmail();

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

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

}

感谢您提供有用的建议!

【问题讨论】:

标签: java concurrency jakarta-mail scheduling scheduledexecutorservice


【解决方案1】:

收集所有在collection中调度后返回的future,然后foreach get()。

【讨论】:

  • ScheduledExecutorService#scheduleAtFixedRate() 只返回一个ScheduledFuture。调用get() 会抛出CancellationException
  • 如果你以固定的速度安排,你希望所有的任务什么时候完成?它将永远重复
  • 不行,因为ScheduledExecutorService已经关闭,所以程序执行会终止。
【解决方案2】:

sf.isCancelled() 呢?这不是您要找的东西?

【讨论】:

  • 不是,因为ScheduledFuture#cancel()是在所有邮件的发送开始后调用的,但是由于它们是异步发送的,所以不清楚发送过程是否真的完成了。所以ScheduledFuture#isCancelled() 将在所有邮件发送(完全)之前返回true,如果发送时间超过传递给ScheduledExecutorService#scheduleAtFixedRate() 的时间/速率。
  • 您的 SendTask 已经从您的主程序中异步调用。为什么你调用邮件程序的异步然后想知道它什么时候完成?您可以使该呼叫同步,删除终止的部分并使用@Eddie 指导的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多