这是我的代码结构的样子
Class TaskA implements runnable {
void run() {
if(not leader node) {
exit this task;
(never run it again)
}
//do stuff
}
};
同样
Class TaskB implements runnable { ....
Class TaskC implements runnable { ....
class Scheduler {
TaskA memberTaskA;
TaskB memberTaskB;
TaskC memberTaskC;
private ScheduledExecutorService executor;
private ScheduledFuture futureA, futureB, futureC;
public Scheduler(TaskA a, TaskB b, TaskC c) {
memberTaskA = a;
memberTaskB = b;
memberTaskC = c;
}
public void start() {
exectuor = Executors.newSingleThreadScheduledExecutor();
futureA = scheduleWithFixedDelay(memberTaskA,
6000,
6000,
TimeUnit.MILLISECONDS);
futureB = scheduleWithFixedDelay(memberTaskB,
6000,
6000,
TimeUnit.MILLISECONDS);
futureC = scheduleWithFixedDelay(memberTaskC,
6000,
6000,
TimeUnit.MILLISECONDS);
}
};
如果在任务的run()方法中满足“不是领导节点”条件,我需要能够不再安排任务。 一种可能的方法是为每个Task创建一个单独的stop方法,如stopTaskA(),stopTaskB()和stopTaskC()。将Scheduler类的对象传递给每个Task并显式调用相应的stopTask()方法。 例如:
stopTaskA(){
futureA.cancel(false);
}
这看起来不是一个非常优雅的解决方案。
任何有关更好设计的想法?
答案 0 :(得分:0)
如何使您的任务实现Callable而不是Runnable。如果他们应该继续运行,则返回true,否则实际上不负责取消自己(关注点的良好分离)。
class TaskCallable implements Callable<Boolean> {
/** Returns true if it should continue to be scheduled, false otherwise */
@Override
public Boolean call() throws Exception {
if (random.nextDouble() < .1) {
System.out.println("FINISHED");
return false;
}
System.out.println("working...");
return true;
}
}
引用/保持类,你上面的“Scheduler”可能看起来像这样(我把它写成了convieneince的单元测试):
private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
@Test
public void test() throws ExecutionException, InterruptedException {
TaskCallable task1 = new TaskCallable();
TaskCallable task2 = new TaskCallable();
TaskCallable task3 = new TaskCallable();
ScheduledFuture<Boolean> future1 = executor.schedule(task1, 100, MICROSECONDS);
ScheduledFuture<Boolean> future2 = executor.schedule(task2, 100, MICROSECONDS);
ScheduledFuture<Boolean> future3 = executor.schedule(task3, 100, MICROSECONDS);
while (future1 != null || future2 != null || future3 != null) {
future1 = reScheduleIfNecessary(future1, task1);
future2 = reScheduleIfNecessary(future2, task2);
future3 = reScheduleIfNecessary(future3, task3);
}
}
其中
/**
* Return NULL if the specified future returns FALSE (indicating it is finished). If the specified future returns
* true then the task is re-scheduled and a new FUTURE is returned. To facilitate polling this method will return
* the passed future if it does not answer in 10 ms.
*/
private ScheduledFuture<Boolean> reScheduleIfNecessary(ScheduledFuture<Boolean> scheduledFuture,
TaskCallable task) throws ExecutionException, InterruptedException {
if (scheduledFuture != null) {
try {
if (scheduledFuture.get(10, TimeUnit.MILLISECONDS)) {
return executor.schedule(task, 100, MICROSECONDS);
}
} catch (TimeoutException e) {
return scheduledFuture;
}
}
return null;
}
您正在重新安排自己,而不是让ScheduledExecutorService为您执行此操作 - 但也许更好地反映了您的意图 - 只有在某些条件为真时再次运行。
您可以轻松地将此概括为N个任务。