Reputation: 367
I'm trying to figure out a way to exit a method call if it takes more then say 2 seconds to execute everything in its method's body. For example, I have a huge list of strings and want to iterate through the list but only iterate as much of the strings as I can in 2 seconds. Say I have 9,000 objects in the list but can only iterate through 6,500 in 2 seconds, the method should stop after 2 second. Is this even possible to accomplish? I searched and found how to stop a thread and timers (how to start a method after a certain duration) but nothing on how to exit a method after a duration.
public ArrayList<String> removeWords(){
//Want some sort of timer here that stops method body after 2 seconds
for(String current: words){
words.remove(current);
}
}
public static void main(String [] args){
ArrayList<String> wordList = removeWords();
System.out.println("Number of words in list "+ wordList.size());
}
Upvotes: 1
Views: 298
Reputation: 20875
Premise: when iterating over a collection, to remove elements you must use the same iterator or you get an exception:
Iterator<String> it = words.iterator();
while (it.hasNext()) {
String word = it.next();
if (shouldRemove(word))
it.remove();
}
If the program you want to stop is a loop and the single iteration does not contain anything that can block you can simply calculate the end instant and check after an X number of iterations:
for (String word : words) {
if (System.currentTimeMillis() > endInstant) {
timedOut = true; // better store this
break;
// ...
}
Otherwise the usual (and more robust) approach is wrapping your program in a Callable<E>
and using a separate thread:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Result> promise = executor.submit(callable);
Result result = promise.get(10, TimeUnits.SECOND);
This way the monitor gets an exception if the result is not ready by the allowed time.
As a final note, consider that the wrapped task will still be running and eating resources, so you may want to set a shouldStop
flag to true
from the main thread to stop the computation as early as possible.
Upvotes: 3
Reputation: 19161
Even interrupting a thread using Thread.interrupt()
requires you to periodically check to see if an interrupt has been requested (using Thread.interrupted()
or Thread.isInterrupted()
), and then decide what to do about it.
So a good general pattern would be to :
long timeout, TimeUnit unit
) in your processing method's parametersSystem.currentTimeMillis()
and TimeUnit.toMillis()
to do the comparisons).What you return if you timeout is up to you, but for interruption you could just throw a new InterruptedException()
.
Of course, if you aren't going to launch your method in a separate thread then you don't need to worry about interruption checking - just the timeouts.
Upvotes: 3