I am iterating over an Iterator
, where hasNext()
will never return false. However, after a specified time (let's say 20 seconds), I want to stop iterating. The problem is that the next()
method of the Iterator
is blocking, but even so, after a specified time, I just need the iteration to stop.
Here is my example Iterable
and Iterator
to 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's blocking
}
}
public Iterator<String> iterator() { return new EndlessIterator(); }
}
Here is my code to test.
EndlessIterable iterable = new EndlessIterable();
for(String s : iterable) { System.out.println(s); }
I wanted to put code/logic into the Iterable
class to create a Timer
, so after the specified time is up, an exception will be thrown 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's 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();
}
}
I then try to test 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");
What I noticed is that the RuntimeException
is thrown after the time is up, however,
- the for loop keeps going,
- the catch block is never reached, and
- i never reach the end of the code (printing done).
Any strategy, approach or design pattern to resolve this problem I've described?
Please note
- in my actual code, i have no control over
Iterator
- i only have control over the
Iterable
and actual iteration