Yeap, I think it is possible. You just have to keep somewhere the deadline for the task and then using a Timer
you can just check if the given TimerTask
should keep running or the timer should be cancelled.
Here's a complete example. It's far from perfect but just is the proof of concept on how should it work.
For a list of Runnable, you start a new ExecuteTask
instance, which internally knows if it should run again, or if they have reach the dead line.
Notice the Runnables are not aware if they would run forever or not at all.
In the code below, I reschedule every second, and the random is within a 10 secs range, but you can reschedule every millisecond, and up to whatever time is reasonable for you.
For instance:
Execute task = new ExecuteTask( new Runnable(){
public void run(){
System.out.println("Hi");
}
});
task.start(); // would run for "random" seconds....
I hope , I have understood what you need.
import java.util.*;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.out;
class ScheduledExecutionDemo {
public static void main( String [] args ) {
List<Runnable> runnables = Arrays.asList( new Runnable[]{
new Runnable(){ public void run(){ out.println("I'm the one");}},
new Runnable(){ public void run(){ out.println("I'm the two");}},
new Runnable(){ public void run(){ out.println("I'm the three");}},
new Runnable(){ public void run(){ out.println("I'm the four");}},
});
for( Runnable run : runnables ) {
new ExecuteTask( run ).start();
}
}
}
class ExecuteTask extends TimerTask {
// This map keeps track on when every task must finish.
// Every time a new instance is created it is stored here
// and every time it is scheduled again checks if it still have time.
private final static Map<Timer, Long> upTo = new HashMap<Timer, Long>();
private final static Random random = new Random();
private final Timer owner;
private final Runnable task;
public ExecuteTask( Runnable task ) {
this.owner = new Timer();
this.task = task;
upTo.put( owner, currentTimeMillis() + random.nextInt( 10 ) * 1000 );
}
public void start() {
owner.schedule( this, 0 , 1000 );
}
public void run() {
if( shouldRunAgain() ) {
task.run();
} else {
owner.cancel();
}
}
private boolean shouldRunAgain() {
return ExecuteTask.upTo.get( owner ) > currentTimeMillis();
}
}
With this proof of concept, you could use a queue and put out the runnables while they are executing and put them back when they have finished their execution, instead of using a simple list.
Also, there might be some synchronization issues, but with the information you provided I think this would be enough.
I hope it helps.