在Java中安排任务

3
在我的Java Web应用程序中,我想要安排一个任务。
我在网上搜索了很多,但是没有找到适合我情况的调度器。在应用程序中,我有不同类型的用户。对于特定的用户类型,我想要安排一个任务。
当用户执行关键操作时:
  • 我想向该特定用户发送电子邮件,并在15分钟后
  • 我想再次发送电子邮件,并在30分钟后
  • 我想发送另一封电子邮件并关闭调度器。
我知道用户何时执行关键操作以及如何发送电子邮件,但是我对调度没有太多经验。
有人可以帮助我处理这个问题吗?

1
在发生关键操作时,你可能想要调度一个Thread - Hungry Blue Dev
5个回答

4

为什么不使用ScheduledExecutor?http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html

它有一个方法schedule,允许您调度任何想要的任务(传递一个可运行的对象)。因此,对于每个用户,您可以安排发送电子邮件和调度另一个任务的任务。

import static java.util.concurrent.TimeUnit.*;

class Task implements Runnable {
   private final User user;
   private final int rep;
   private final ScheduledExecutorService scheduler;

   public Task(User user, int rep, ScheduledExecutorService scheduler) {
       this.user = user;
       this.rep = rep;
       this.scheduler = scheduler;
   }

   public void run() {
       // send an e-mail to user
       if (rep > 0)
           scheduler.schedule(new Task(user, rep - 1, scheduler), 15, MINUTES);
   }
}

class Example {
    private final ScheduledExecutorService scheduler =
        Executors.newScheduledThreadPool(1);

    public void sendEmails() {
        // foreach user
        scheduler.submit(new Task(user, 3, scheduler));
    }
}

您可能需要使用一个计划任务线程池,其中有多个线程。


你能帮我使用ManagedScheduledExecutorService创建相同的任务吗?我需要创建一个每天下午5点运行的作业。这是一个Web应用程序。我已经搜索了很多,但仍然无法完成。 - Shruti sharma
1
@ShwetaMishra 为什么不使用 Triggerschedule 方法呢?这里的第二个示例几乎是您所需的:https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/Trigger.html - ciamej
谢谢您的回复。实际上这是一个 web 应用程序,我必须使用 ManagedScheduledExecutorService 类。ScheduledExecutorService 类存在的问题是,如果出现任何异常,它不会报告,而是使代码崩溃。 - Shruti sharma
@ShwetaMishra 我不确定ManagedScheduledExecutorService和ScheduledExecutorService在异常处理方面有何区别,但我建议使用ManagedScheduledExecutorService的schedule方法。如果这不能解决你的问题,请考虑在SO上发布一个单独的问题。 - ciamej

2

使用Quartz Scheduler来安排任务。

所需步骤 -

1)创建 Quartz 工作。

public class HelloJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
    System.out.println("Hello Quartz!");    
    }
}

2)创建触发器 - CronTrigger - 每30秒运行一次

CronTrigger trigger = new CronTrigger();
trigger.setName("dummyTriggerName");
trigger.setCronExpression("0/30 * * * * ?");

3) 创建一个调度器

Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);

1

这是一个关于如何使用Java计时器的教程: http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html

您可以按顺序创建多个计时器任务以实现您的目标。

示例代码引用:

import java.util.Timer;
import java.util.TimerTask;

/**
 * Simple demo that uses java.util.Timer to schedule a task 
 * to execute once 5 seconds have passed.
 */

public class Reminder {
Timer timer;

public Reminder(int seconds) {
    timer = new Timer();
    timer.schedule(new RemindTask(), seconds*1000);
}

class RemindTask extends TimerTask {
    public void run() {
        System.out.format("Time's up!%n");
        timer.cancel(); //Terminate the timer thread
    }
}

public static void main(String args[]) {
    new Reminder(5);
    System.out.format("Task scheduled.%n");
}
}

0

我建议你看一下quartz调度API http://quartz-scheduler.org/

到目前为止,我已经在几个项目中使用它了,它非常容易设置和配置新的作业。它支持基于cron的触发器或简单触发器,因此您可以在Java代码中计算计划事件的时间,也可以简单地传递一个cron字符串。

另一个优点是它与Spring非常容易配置。


0
您也可以使用JobRunr,它是一个易于使用的开源Java调度程序
要在15分钟后使用JobRunr安排作业,您可以使用以下代码:
JobId firstEmailJobId = BackgroundJob.enqueue(() -> yourService.sendFirstEmail());

JobId secondEmailJobId = BackgroundJob.schedule(Instant.now().plus(15, minutes), () -> yourService.sendSecondEmail());

您可以按照同样的步骤重复执行另外两封电子邮件。如果您想取消发送这些电子邮件(例如用户采取了行动),只需使用JobId再次删除这些任务即可(前提是该任务尚未执行)。
JobRunr还具有自动重试功能(例如,您的邮件服务器或sendgrid出现故障),以及一个嵌入式仪表板,可以让您跟踪作业的进展情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接