How to implement a efficient timeout in java

前提是你 提交于 2019-12-05 02:14:32

问题


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?


回答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
 }



回答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.




回答3:


Interrupt the thread every time you update a timestamp. Then it will loop, find nothing to do, sleep, and if nothing else has happened to the timestamp, expire it. If it gets interrupted a second time, so much the better. And at all times it should never sleep for longer than 60 minus (current time minus the oldest timestamp).



来源:https://stackoverflow.com/questions/11629267/how-to-implement-a-efficient-timeout-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!