java在将来某个时间运行事件

iyfjxgzm  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(375)

我正在用jersey设计一个javaweb应用程序,在mysql数据库中有一个日期时间字段“future\u time”。我也是一个在同一个表中有一个状态字段设置为挂起。如果当前时间>=未来时间,我想更新status字段为completed in db。好像我想安排一个活动。
其次,如果当前时间<未来时间,并且如果我更新了未来时间值,我想重新安排上一个事件。
当前,每当我获取status字段时,我都会检查它是否挂起,如果它挂起,那么我会检查future\u time是否<=current\u time,如果是,那么我会将db中的status字段更新为completed。但这里面有个问题。这只会在我获取状态字段时更新它。因此,如果我在很长一段时间之后(在未来的\时间之后)获取status字段,那么它将在那一刻被更新,在db中保存不正确的记录。
有人能给我一个更好的方法来实现这个目标吗?

2j4z5cfb

2j4z5cfb1#

计算截止日期前经过的时间

对于JDBC4.2和更高版本,使用现代的java.time类检索日期时间。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class );  // Likely to be a UTC value.

获取当前时刻。

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;

计算经过的时间。

Duration d = Duration.between( now , odt ) ;

计划事件

使用现代的executor框架,而不是遗留的 Timer 班级。在servlet或jakarta.ee(javaee)环境中尤其如此。
定义你的执行者,特别是 ScheduledExecutorService . 我们只需要一个线程来完成这个任务。

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()

让执行器等待一定的时间,然后运行代码检查数据库中的状态。

myExecutorService.schedule(           // Tell the executor what you want to run, and when you want it run on your behalf in a background thread.
    new Runnable() { … } ,            // Define task to be executed as a `Runnable`.
    d.toSeconds() ,                   // Amount of time to wait until execution. Use self-documenting code rather than a “magic number” such as `86400000`. 
    TimeUnit.SECONDS                  // Specify the granularity of time used in previous pair of arguments.
)                                     // Returns a `ScheduledFuture` which you may want to cache.

或者,您可以捕获 ScheduledFuture 由此返回 schedule 声明。然后可以监视完成状态。
在你的 Runnable ,从数据库中检索当前状态记录。如果需要,安排另一次执行,使用新的当前时刻重新计算等待时间。

servlet web容器

对于没有完整jakarta.ee堆栈的servlet web容器,如tomcat或jetty,上面的讨论适用。
此外,您还需要编写一个实现 ServletContextListener 接口,您可以设置和拆除您的执行器服务。你需要优雅地拆除executor服务,这样它的后台线程就不会在你的web应用关闭后很长一段时间内愉快地继续运行了。

雅加达ee

如果在一个完整的jakarta.ee堆栈(如glassfish)中,这项工作要容易得多。
上面看到的executor服务可以自动化,并代表您进行设置和拆卸。使用jsr 236:concurrency utilities for javatm ee中定义的并发实用程序。这已经被讨论过很多次了,所以搜索堆栈溢出以获取更多信息。

关于java.time

java.time框架内置于Java8及更高版本中。这些类取代了旧的遗留日期时间类,例如 java.util.Date , Calendar , & SimpleDateFormat .
现在处于维护模式的joda time项目建议迁移到java.time类。
要了解更多信息,请参阅oracle教程。和搜索堆栈溢出的许多例子和解释。规格为jsr 310。
您可以直接与数据库交换java.time对象。使用符合jdbc 4.2或更高版本的jdbc驱动程序。不需要线,不需要线 java.sql.* 班级。
从哪里获得java.time类?
JavaSE8、JavaSE9、JavaSE10、JavaSE11及更高版本—标准JavaAPI的一部分,带有捆绑实现。
Java9添加了一些次要的特性和修复。
java se 6和java se 7
大部分java.time功能都是通过三个十个后端口后端口移植到Java6和Java7的。
安卓
android包java.time类的更高版本实现。
对于早期的android(<26),threetenabp项目采用了threeten backport(如上所述)。了解如何使用threetenabp…。
threeten额外的项目用额外的类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,例如 Interval , YearWeek , YearQuarter ,等等。

ftf50wuq

ftf50wuq2#

你可以用 ScheduledExecutorService 用于在特定的时间间隔、固定的延迟或特定的时间点安排任务。
您可以创建 ScheduledExecutorService 比如:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

然后使用服务安排作业,如:

//scheduling at fixed time.
Future<String> resultFuture = executorService.schedule(new Callable<String>() {
    @Override
    public String call() throws Exception
    {
        //your code;
    }
}, 1, TimeUnit.SECONDS);

//scheduling at fixed intervals.
executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run()
    {
        //your code
    }
}, 100, 450, TimeUnit.MILLISECONDS);

//scheduling at fixed delays.
executorService.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run()
    {
        //your code
    }
}, 100, 150, TimeUnit.MILLISECONDS);

您也可以使用java定时器实用程序来为将来安排任务,但是java规范说更喜欢 ScheduledExecutorService . 下面是一个使用计时器调度作业的示例代码。

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;

/**
 * An example for Java Timer Utility.
 *
 * @author Karan Khanna.
 */
public class TimerExample
{

    public static void scheduleTaskForFuture(final Date date)
    {
        Timer timer = new Timer("Timer");
        TimerTask task = new TimerTask()
        {
            public void run()
            {

                System.out.println(
                    String
                        .format("Task performed on: %s and Thread's name: %s", date, Thread.currentThread().getName()));

                timer.cancel();
            }
        };
        timer.schedule(task, date);
    }

    public static void main(final String[] args)
    {
        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.MINUTE, 1);
        TimerExample.scheduleTaskForFuture(calendar.getTime());
    }
}

您可以更深入地研究该实用程序以安排重复的任务。另外,一旦完成了所需的工作,不要忘记取消任务。
您也可以为此尝试其他框架,如quartz和spring调度。

相关问题