How to implement a efficient timeout in java
Solution 1
I think using a monitor object with wait/notify is reasonable (you may use Condition with await/signal if you are using JDK >= 5)
idea is simple:
Worker thread:
doYourActualWork();
synchronized(jobFinishedMonitor) {
updateTimestamp();
jobFinishedMonitor.notify();
}
Timeout thread:
synchronized(jobFinishedMonitor) {
while(within60Second(timestamp)) {
jobFinishedMonitor.wait(60);
}
if (within60Second(timestamp)) {
timeoutHappened=true;
}
}
if (timeoutHappened) {
// do timeout handling
}
Solution 2
For the question, it's not clear what you want to do with the timeout. Here I present you two options to implement a lightweight timeout: monitored vs controlled.
Monitored Timeout
For a global timer, you can use the Timer
facility from the 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
There's a similar construction possible using 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);
I prefer the ScheduledExecutorService
above the Timer
facility, as the SchedulerExecutor
can hold a pool of threads. Also, the underlying threadpool can be used for other operations invoking scheduledExecutorService.execute(...)
for immediate concurrent execution (not scheduled), making it a generic executor facility, rather than a dedicated timer function.
In both cases, you'll need to take special care to safely get the timeout value from your the objects you are monitoring. Typically, you will use a synchronized method in the object to ask for it's timeout status.
Enforced Timeout
The ExecutorService provides you with an API to execute a set of tasks within a given timeout. e.g.
List<Callable<?>> myTasks = ...;
// populate myTasks with Callable`s that wrap your intended execution
ExecutorService executorService = ... ;
List<Future<?>> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS);
After this method returns, you can ask every Future whether it succeeded within the time given.
stormsam
Updated on June 04, 2022Comments
-
stormsam almost 2 years
There are
n
object which perform some actions. After performing an action a timestamp will be updated. Now I want to implement a timeout-thread which verifies if a timestamp is older than for example 60 seconds.My first solution was to do that with a thread (while-loop + sleep) which is holding a list with all objects including the last timestamp. Now I have the problem that there is a worst-case scenario where the thread needs 59 seconds plus sleep time to decide for a timeout.
I’m searching for a solution like a Timer where it is possible to update the delay time.
Any ideas?