有n
执行某些动作的对象。执行操作后,时间戳将被更新。现在我想实现一个超时线程来验证时间戳是否早于例如 60 秒。
我的第一个解决方案是使用一个线程(while-loop + sleep)来做到这一点,该线程包含一个包含所有对象的列表,包括最后一个时间戳。现在我遇到的问题是,在最坏的情况下,线程需要 59 秒加上睡眠时间来决定超时。
我正在寻找一个像 Timer 这样的解决方案,可以更新延迟时间。
有任何想法吗?
有n
执行某些动作的对象。执行操作后,时间戳将被更新。现在我想实现一个超时线程来验证时间戳是否早于例如 60 秒。
我的第一个解决方案是使用一个线程(while-loop + sleep)来做到这一点,该线程包含一个包含所有对象的列表,包括最后一个时间戳。现在我遇到的问题是,在最坏的情况下,线程需要 59 秒加上睡眠时间来决定超时。
我正在寻找一个像 Timer 这样的解决方案,可以更新延迟时间。
有任何想法吗?
我认为使用带有等待/通知的监视器对象是合理的(如果您使用 JDK >= 5,则可以使用带有等待/信号的条件)
想法很简单:
工作线程:
doYourActualWork();
synchronized(jobFinishedMonitor) {
updateTimestamp();
jobFinishedMonitor.notify();
}
超时线程:
synchronized(jobFinishedMonitor) {
while(within60Second(timestamp)) {
jobFinishedMonitor.wait(60);
}
if (within60Second(timestamp)) {
timeoutHappened=true;
}
}
if (timeoutHappened) {
// do timeout handling
}
对于这个问题,不清楚你想用超时做什么。在这里,我向您展示了实现轻量级超时的两个选项:受监控的与受控的。
监控超时
对于全局计时器,您可以使用Timer
JDK 中的工具:
public TimeoutTask implements TimerTask {
List<MonitorableObject> objects;
public TimeoutTask(List<MonitorableObject> objects) {
// make sure you can share this collection concurrently,
// e.g. copyonwritearraylist
this.objects = objects;
}
public void run() {
// objects -> filter(isTimeOut(currentTime)) -> do something
}
}
Timer timer = new Timer();
timer.schedule(new TimeoutTask(myObjectList), 0,60*1000); // repeat each 60secs
使用 a 可以进行类似的构造ScheduledExecutorService
:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// Note that I can use here TimeoutTask b/c TimerTask is a Runnable -
// this is just for the example. You'd better implement a plain runnable.
scheduler.schedule(new TimeoutTask(myObjectList), 60, TimeUnit.SECONDS);
我更喜欢ScheduledExecutorService
上面的Timer
设施,因为它SchedulerExecutor
可以容纳一个线程池。此外,底层线程池可用于调用scheduledExecutorService.execute(...)
立即并发执行(未调度)的其他操作,使其成为通用执行器工具,而不是专用的计时器功能。
在这两种情况下,您都需要特别注意从您正在监视的对象中安全地获取超时值。通常,您将在对象中使用同步方法来询问它的超时状态。
强制超时
ExecutorService 为您提供了一个 API,可以在给定的超时时间内执行一组任务。例如
List<Callable<?>> myTasks = ...;
// populate myTasks with Callable`s that wrap your intended execution
ExecutorService executorService = ... ;
List<Future<?>> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS);
此方法返回后,您可以在给定的时间内询问每个 Future 是否成功。
每次更新时间戳时中断线程。然后它将循环,无事可做,休眠,如果时间戳没有发生任何其他事情,则将其过期。如果它被第二次中断,那就更好了。并且在任何时候,它的睡眠时间都不应超过 60 减(当前时间减去最旧的时间戳)。