我正在尝试同时使用ExecutorCompletionService和ScheduledExecutorService。我需要做的是安排不同的活动,每个活动都有“执行前的延迟”并且根据上一次运行的结果“重新安排它们”(拥有不同的延迟时间)。
我的问题是,我无法在ExcecutorCompletionService submit中使用“延迟”。
我尝试了以下方法,但它会永远阻塞...
显然我忽略了Java语言中的一个基本问题。
是否有任何方式可以安排任务到ScheduledExecutorService,使CompletionService“知道它”?
如果我在Callable中设置"delay",通过new ActionOne(delay)创建callable,并使用CompletionService.submit(..),它可以工作。
我的问题是,我无法在ExcecutorCompletionService submit中使用“延迟”。
我尝试了以下方法,但它会永远阻塞...
显然我忽略了Java语言中的一个基本问题。
是否有任何方式可以安排任务到ScheduledExecutorService,使CompletionService“知道它”?
public class Bar {
private ScheduledExecutorService scheduledExecutor;
private Future<Status> action1Future;
private Future<Status> action2Future;
private ExecutorCompletionService<Status> pool;
private long delay1 = 10;
private long delay2 = 20;
private long delay3 = 30;
public void start() {
scheduledExecutor = Executors.newScheduledThreadPool(3);
Action1 a1 = new ActionOne(); // Action1 implements Callable<Status>
Action2 a2 = new ActionTwo(); // Action2 implements Callable<Status>
pool = new ExecutorCompletionService<Status>(scheduledExecutor);
action1Future = scheduledExecutor.schedule(a1, delay1, TimeUnit.SECONDS);
action2Future = scheduledExecutor.schedule(a2, delay1, TimeUnit.SECONDS);
monitorAndRestart();
}
private void monitorAndRestart() {
boolean isDone=false;
do {
try {
// THIS IS WHERE IT BLOCKS.
Future<Status> processedItem = pool.get();
if (processedItem == action1Future) {
if (processedItem.get() == Status.GOOD) {
action1Future = scheduledExecutor.schedule(new ActionOne(), delay1, TimeUnit.SECONDS);
} else {
action1Future = scheduledExecutor.schedule(new ActionOne(), delay2, TimeUnit.SECONDS);
}
} else if (processedItem == action2Future) {
if (processedItem.get() == Status.GOOD) {
action1Future = scheduledExecutor.schedule(new ActionOne(), delay2, TimeUnit.SECONDS);
} else {
action1Future = scheduledExecutor.schedule(new ActionOne(), delay3, TimeUnit.SECONDS);
}
}
} catch (InterruptedException e) {
isDone = true;
// handle this.. shudown whatever
}
catch (ExecutionException e) {
// handle this
}
} while (isDone == false);
}
public static void main(String[] args) {
Bar myRunner = new Bar();
myRunner.start();
}
}
如果我在Callable中设置"delay",通过new ActionOne(delay)创建callable,并使用CompletionService.submit(..),它可以工作。
actionFuture1 = pool.submit(new ActionOne(delay1));
/////
public class ActionOne implements Callable<Status>(
private final delay;
public ActionOne(long dl) {
delay=dl;
}
Status call() {
try {
Thread.sleep(delay * 1000); // seconds
return doSomething()
} catch (...) { //thread.sleep execptions}
}
}
所以我猜最终的问题是:使用ScheduledExecutorService相比于Thread.sleep(delay)的方式,有什么根本上更好的地方吗?
ExecutorCompletionService
没有做任何其他事情,只是包装了任务... - HolgerafterExecute(Runnable, Throwable)
(为什么?!)。我猜想这个选项不能用于Callable
? - Jakob