如何在java中实现有效的超时

n对象执行某些操作。 执行操作后,将更新时间戳。 现在我想实现一个超时线程,它validation时间戳是否早于例如60秒。

我的第一个解决方案是使用一个线程(while-loop + sleep)执行该操作,该线程包含一个包含所有对象(包括最后一个时间戳)的列表。 现在我遇到的问题是,最糟糕的情况是线程需要59秒加上睡眠时间来决定超时。

我正在寻找像Timer这样的解决方案,可以更新延迟时间。

有任何想法吗?

我认为使用带有wait / notify的监视对象是合理的(如果使用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 } 

对于这个问题,目前尚不清楚你想要对超时做什么。 在这里,我向您展示了两种实现轻量级超时的选项:监控与受控。

监控超时

对于全局计时器,您可以使用JDK中的Timer工具:

 public TimeoutTask implements TimerTask { List objects; public TimeoutTask(List objects) { // make sure you can share this collection concurrently, // eg 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 

使用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); 

我更喜欢Timer工具上面的ScheduledExecutorService ,因为SchedulerExecutor可以容纳一个线程池。 此外,底层线程池可用于调用scheduledExecutorService.execute(...)以进行即时并发执行(未调度)的其他操作,使其成为通用执行器工具,而不是专用计时器function。

在这两种情况下,您都需要特别注意从您正在监视的对象中安全地获取超时值。 通常,您将在对象中使用synchronized方法来询问其超时状态。

强制超时

ExecutorService为您提供了一个API,用于在给定的超时内执行一组任务。 例如

 List> myTasks = ...; // populate myTasks with Callable`s that wrap your intended execution ExecutorService executorService = ... ; List> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS); 

在此方法返回后,您可以询问每个Future是否在给定的时间内成功。

每次更新时间戳时都会中断线程。 然后它将循环,找不到任何操作,睡眠,如果时间戳没有发生任何其他事件,则将其终止。 如果它第二次被打断,那就更好了。 并且在任何时候都不应该睡眠超过60减去(当前时间减去最旧的时间戳)。