每个月我都想用Java运行某个任务。但是,我无法在此计算机上访问cron系统或Java环境之外的任何内容。
实施此类系统的最有效方法是什么,或者是否存在某人可以为我提供链接的系统?我会将当前时间存储在文件中,然后像每天一样,比较它以查看差异是否为一个月,如果是,则运行并重置。但这不是最准确的方法。
答案 0 :(得分:3)
编写一个小程序,让操作系统处理每月执行。在Windows下使用task scheduler或在Linux下使用cronjob。
答案 1 :(得分:0)
有几种选择:
答案 2 :(得分:0)
现代Java包含出色的 Executor 框架,可轻松安排在后台线程上完成的工作。参见Tutorial。特别是,您需要ScheduledExecutorService
。
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( 1 ) ;
要求该调度程序在经过一定时间后运行Runnable
任务。
scheduler.schedule( runnable , delay , timeUnit ) ;
因此,接下来您需要确定需要经过的时间。
定义您的目标,即每月的某天。 ThreeTen-Extra库为此提供了一个类DayOfMonth
。
DayOfMonth domTarget = DayOfMonth.of( 15 ) ;
获取要查看日历的时区中所显示的当前时刻。请记住,在任何给定时刻,日期随时区变化在全球各地。在东京的日期可能是“明天”,而在蒙特利尔的日期可能是“昨天”。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
获取今天的月份。
DayOfMonth domToday = DayOfMonth.from( now ) ;
提取当前日期,仅提取日期,没有日期和时区。
LocalDate today = now.toLocalDate() ;
比较今天和目标之间的每月日期。如果今天已超过目标,请移至下个月。
LocalDate target = domTarget.atYearMonth( YearMonth.of( today ) ) ; // Get the date for our target day-of-month in the current month (current year-month).
if( ! target.IsAfter( today ) ) {
target = target.plusMonths( 1 ) ; // If target is not after today, move to the next month.
}
获取目标日期的第一天。不要以为一天从00:00开始。在某些区域中的某些日期,一天可能会在其他时间开始,例如01:00。
ZonedDateTime start = target.atStartOfDay( z ) ; // Determine the first moment of the day on that date in that zone.
现在,我们可以确定从现在到我们要运行任务的开始时间之间的经过时间。将此未附加到时间轴的时间跨度表示为Duration
。在内部,此类是整个秒的计数加上分数的秒。
Duration d = Duration.between( now , start ) ; // Calculate elapsed time.
最后,我们可以告诉调度程序一段时间。我们使用TimeUnit
枚举指定粒度。
scheduler.schedule( runnable , d.toSeconds() , TimeUnit.SECONDS ) ; // Tell our ScheduledExecutorService to run some code after the specified time to wait.
请确保在您的应用结束时正常关闭执行程序服务,否则其线程可能会在您的应用结束后继续运行。
注意:我未经测试就将这段代码写在了头上。因此,它可能并不完美,但应该使您朝正确的方向前进。