Reputation: 2260
I have an infinite loop inside my main, it runs a job which is also an infinite loop, and wait for it to throw an error. Then it sleeps for a given amount of time and starts the task again.
public static void main(String[] args) {
while (true) {
try {
MyClass myClass = new MyClass();
myClass.startInfiniteLoop();
}
catch (SomeException ex) {
try {
Thread.sleep(MyClass.DEFAULT_SLEEP_TIME);
}
catch (InterruptedException ex2) {
System.exit(-1);
}
}
}
}
This works fine, but I wonder if this could be done better, perhaps with an ExecutorService
as I (and my IDE) don't like Thread.sleep()
in a while (true)
loop.
I have read a lot of questions and their answers about ScheduledExecutorService
and task management, but I did not find this particular case since it's not really a schedule, I don't know if and when the task if going to end.
Upvotes: 0
Views: 3926
Reputation: 70929
If you can take the MyClass and rework it to have a Runnable that does what only one loop iteration of the MyClass would have done, then you can use a scheduling executor service, telling the service to run the Runnable once every time period.
--- Updated by request of a quick example ---
The following is not strictly correct Java code, it is pesudo-java.
public class MyRepeatingTask implements Runnable {
private final ScheduledThreadpoolExecutor executor;
public MyRepeatingTask(ScheduledThreadpoolExecutor executor) {
this.executor = executor;
}
public void run() {
try {
doMyVariableLengthThing();
// alternatively, you could also schedule a new instance
executor.schedule(this, 1, TimeUnit.SECONDS);
} catch (Exception e) {
cleanup();
}
}
}
and then to start the ball rolling
ScheduledThreadpoolExecutor executor = new ScheduledThreadpoolExecutor(1);
executor.execute(new MyRepeatingTask(executor));
Upvotes: 0
Reputation: 298389
You can use a ScheduledExecutorService
:
ScheduledExecutorService s=Executors.newScheduledThreadPool(1);
s.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
MyClass myClass = new MyClass();
myClass.startInfiniteLoop();
} catch(SomeException ex) {}
}
}, 0, MyClass.DEFAULT_SLEEP_TIME, TimeUnit.MILLISECONDS);
The key point is to use scheduleWithFixedDelay
rather than scheduleAtFixedRate
to ensure the specified time elapses between the subsequent executions just like with your sleep
approach. However, note that even with “fixed rate” the new execution will not start when the old one has not finished yet. It’s documentation says: “If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.”
Further note that you still have to catch the exception like in my code example as otherwise the executor will cancel the scheduled task once it threw an uncatched exception.
Upvotes: 3