Да, я думаю, что это возможно. Вам просто нужно сохранить где-то крайний срок для задания, а затем, используя Timer
, вы можете просто проверить, должен ли данный TimerTask
продолжать работать или таймер должен быть отменен.
Вот полный пример. Это далеко от совершенства, но это лишь доказательство того, как это должно работать.
Для списка Runnable вы запускаете новый экземпляр ExecuteTask
, который внутренне знает, должен ли он работать снова, или они достигли мертвой линии.
Обратите внимание, что Runnables не знают, будут ли они работать вечно или нет вообще.
В приведенном ниже коде я перепланирую каждую секунду, и случайное значение находится в диапазоне 10 секунд, но вы можете перепланировать каждую миллисекунду и в любое удобное для вас время.
Например:
Execute task = new ExecuteTask( new Runnable(){
public void run(){
System.out.println("Hi");
}
});
task.start(); // would run for "random" seconds....
Надеюсь, я понял, что вам нужно.
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();
}
}
С этим доказательством концепции вы могли бы использовать очередь и выставить исполняемые объекты во время их выполнения и вернуть их обратно после завершения выполнения вместо использования простого списка.
Кроме того, могут быть некоторые проблемы с синхронизацией, но с предоставленной вами информацией, я думаю, этого будет достаточно.
Надеюсь, это поможет.