What is the best way to break out of an iteration after a certain time?

I repeat Iteratorwhere it hasNext()never returns false. However, after a certain time (say 20 seconds), I want to stop the iteration. The problem is that the method is next() Iteratorblocked, but even then, after a certain time, I just need the iteration to stop.

Here is my example Iterableand Iteratorto simulate my problem.

public class EndlessIterable implements Iterable<String> {
    static class EndlessIterator implements Iterator<String> {
         public boolean hasNext() { return true; }
         public String next() { 
             return "" + System.currentTimeMillis(); //in reality, this code does some long running task, so it blocking
         }
    }
   public Iterator<String> iterator() { return new EndlessIterator(); }
}

Here is my code for testing.

EndlessIterable iterable = new EndlessIterable();
for(String s : iterable) { System.out.println(s); }

I wanted to put the code / logic into the class Iterableto be created Timer, so after the specified time has passed, the exception will be chosen so as to stop the iteration.

public class EndlessIterable implements Iterable<String> {
    static class EndlessIterator implements Iterator<String> {
        public boolean hasNext() { return true; }
        public String next() { 
            try { Thread.sleep(2000); } catch(Exception) { } //just sleep for a while
            return "" + System.currentTimeMillis(); //in reality, this code does some long running task, so it blocking
        }
    }
    static class ThrowableTimerTask extends TimerTask {
        private Timer timer;
        public ThrowableTimerTask(Timer timer) { this.timer = timer; }
        public void run() {
            this.timer.cancel();
            throw new RuntimeException("out of time!");
        }
    }
    private Timer timer;
    private long maxTime = 20000; //20 seconds
    public EndlessIterable(long maxTime) {
        this.maxTime = maxTime;
        this.timer = new Timer(true);
    }
    public Iterator<String> iterator() { 
        this.timer.schedule(new ThrowableTimerTask(this.timer), maxTime, maxTime);
        return new EndlessIterator();
    }
}

Then I will try to check this code as follows.

EndlessIterable iterable = new EndlessIterable(5000);
try {
    for(String s : iterable) { System.out.println(s); }
} catch(Exception) {
    System.out.println("exception detected: " + e.getMessage());
}
System.out.println("done");

, , , RuntimeException , ,

  • for ,
  • catch ,
  • ( ).

, , ?

:

  • , Iterator
  • Iterable
+4
4

. - , . -, , , , Iterator. /:

// an iterator wrapping another one adding the timeout functionality
class TimeOutIterator<T> implements Iterator<T> {
  final Iterator<T> source;
  final long deadline;

  public TimeOutIterator(Iterator<T> dataSource, long timeout, TimeUnit unit) {
    source=dataSource;
    deadline=System.nanoTime()+unit.toNanos(timeout);
  }
  private void check() {
    if(System.nanoTime()-deadline >= 0)
      throw new RuntimeException("timeout reached");
  }
  public boolean hasNext() {
    check();
    return source.hasNext();
  }
  public T next() {
    check();
    return source.next();
  }
  public void remove() {
    check();
    source.remove();
  }
}

, :

public class EndlessIterable implements Iterable<String> {
  static class EndlessIterator implements Iterator<String> {
   public boolean hasNext() { return true; }
   public String next() { 
     // dummy code illustrating the long running task
     try { Thread.sleep(2000); } catch(Exception e) { }
     return "" + System.currentTimeMillis();
   }
   public void remove() { throw new UnsupportedOperationException(); }
  }
  private long maxTime;
  private TimeUnit unit;

  public EndlessIterable(long maxTime, TimeUnit timeUnit) {
    this.maxTime = maxTime;
    this.unit = timeUnit;
  }
  public Iterator<String> iterator() { 
    return new TimeOutIterator<>(new EndlessIterator(), maxTime, unit);
  }
}

:

// should timeout after five seconds
EndlessIterable iterable = new EndlessIterable(5, TimeUnit.SECONDS);
try {
 for(String s : iterable) { System.out.println(s); }
} catch(Exception e) {
  System.out.println("exception detected: " + e);
}
System.out.println("done");
+1

. , , interrupt() . , ; , , .

, . BlockingQueue. , . , . , , , .

, , , .

+1

Thread -

Thread.sleep(20)

0

You have a thread that sleeps for your time, and then calls Thread.interrupt()in the thread that iterates, and then every time through the loop you can check if there is a thread isInterrupted()and exit the loop if it is ever true.

You can also use inline Timerinstead of calling Thread.sleep(); which approach is best for you will depend on what your calling thread is doing, etc.

0
source

All Articles