Runnable
定义作为一个团队需要完成的工作
Runnable
.
Scheduled ExecutorService
要每隔一分钟左右运行一次,请检查当前日期与目标日期。如果倒计时已增加,则更新GUI中的显示。如果没有,什么也不做,让
可运行
再跑一分钟。
Oracle Tutorial on Executors
.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); // Use a single thread, as we need this to run sequentially, not in parallel.
ses.scheduleWithFixedDelay( r , 0L , 1L , TimeUnit.MINUTES ); // Pass the `Runnable`, an initial delay, a count to wait between runs, and the unit of time for those two other number arguments.
安排一次新的旅行会更有效率
可运行
每次,而不是自动重复,以便将延迟设置为直到下一个午夜的计算时间量。这样,遗嘱执行人就可以整天睡觉,而不是分秒必争。但是,如果用户的时钟更新到明显不同的当前时间,或者如果用户当前的默认时区发生变化(如果您依赖默认时区而不是明确设置默认时区),这种方法可能会失控。考虑到这一点
可运行
LocalDate
这个
LocalDate
类表示一个仅日期的值,该值不包含一天中的时间,也不包含
time zone
offset-from-UTC
.
Paris France
Montréal Québec
.
如果未指定时区,JVM将隐式应用其当前默认时区。这一违约可能会发生
change at any moment
在运行时(!),因此您的结果可能会有所不同。最好将所需/预期时区明确指定为参数。
指定一个
proper time zone name
Continent/Region
例如
America/Montreal
,
Africa/Casablanca
或
Pacific/Auckland
. 切勿使用2-4个字母的缩写,如
EST
或
IST
不
真正的时区,没有标准化,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Asia/Kolkata" ); // Or ZoneId.systemDefault() to rely on the JVMâs current default time zone.
LocalDate today = LocalDate.now( z );
实例
这是一个完整的例子。有关详细信息,请搜索堆栈溢出。使用
ScheduledExecutorService
已经被报道过很多次了。
package work.basil.example;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class DailyCountdown implements Runnable {
private LocalDate dueDate;
private Long daysRemaining;
public DailyCountdown ( LocalDate dueDate ) {
this.dueDate = dueDate;
}
@Override
public void run () {
try {
System.out.println( "DEBUG - Running the DailyCountdown::run method at " + Instant.now() );
ZoneId z = ZoneId.of( "America/Montreal" ); // Or ZoneId.systemDefault() to rely on the JVMâs current default time zone.
LocalDate today = LocalDate.now( z );
Long count = ChronoUnit.DAYS.between( today , this.dueDate );
if ( Objects.isNull( this.daysRemaining ) ) {
this.daysRemaining = ( count - 1 );
}
if ( this.daysRemaining.equals( count ) ) {
// Do nothing.
} else {
// ⦠Schedule on another thread for the GUI to update with the new number.
this.daysRemaining = count;
}
} catch ( Exception e ) {
// Log this unexpected exception, and notify sysadmin.
// Any uncaught exception reaching the scheduled executor service would have caused it to silently halt any further scheduling.
}
}
public static void main ( String[] args ) {
// Put this code where ever appropriate, when setting up your GUI after the app launches.
Runnable r = new DailyCountdown( LocalDate.of( 2018 , Month.FEBRUARY , 15 ) );
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleWithFixedDelay( r , 0L , 1L , TimeUnit.MINUTES );
// Be sure to gracefully shutdown the ScheduledExecutorService when your program is stopping. Otherwise, the executor may continue running indefinitely on the background thread.
try {
Thread.sleep( TimeUnit.MINUTES.toMillis( 7 ) ); // Sleep 7 minutes to let the background thread do its thing.
} catch ( InterruptedException e ) {
System.out.println( "The `main` thread was woken early from sleep." );
}
ses.shutdown();
System.out.println( "App is exiting at " + Instant.now() ) ;
}
}