1

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());
}
seenukarthi
  • 8,241
  • 10
  • 47
  • 68
Calvin Jones
  • 357
  • 7
  • 19
  • 2
    google is a great tool. This was the first article returned from the search "stop program execution after 1 second java" http://stackoverflow.com/questions/4252187/how-to-stop-execution-after-a-certain-time-in-java – SaggingRufus Aug 28 '15 at 16:58
  • There's no way to know how long some code will take to execute before it runs (we can guess its time complexity, but not a precise time). If you only want to execute a bulk of code for n seconds, a `Timer` of some description is what you need. Knowing how long code will take to run would solve the Halting Problem. – TEK Aug 28 '15 at 16:58
  • the anwser to that link doesn't help, i've seen the article though – Calvin Jones Aug 28 '15 at 17:08
  • If i implemented that while loop then i would iterate through the entire list and only would stop once the for each loop completes and check the while condition the second time around – Calvin Jones Aug 28 '15 at 17:12
  • @Calvin is there some way for you to iterate over a single item per loop? – CubeJockey Aug 28 '15 at 17:15

2 Answers2

3

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 :

  1. Accept a timeout (the usual pattern is long timeout, TimeUnit unit) in your processing method's parameters
  2. Periodically (every n iterations of your loop, or even every iteration if it doesn't hurt your performance) check for the timeout and for interruption (using System.currentTimeMillis() and TimeUnit.toMillis() to do the comparisons).
  3. return if either occurs

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.

Andy Brown
  • 18,961
  • 3
  • 52
  • 62
3

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.

Raffaele
  • 20,627
  • 6
  • 47
  • 86