我试图创建一个执行中的最大时间量给定任务的方法。 如果它不能在该时间内完成,就应该放弃之前的重试次数。 还应该等待数的每个尝试之间秒。 下面是我想出的,我想对我的做法有些批评。 是他们的一个简单的方法来做到这一点使用ScheduledExecutorService
或者是我做这足够了呢?
public static <T> T execute(Callable<T> task, int tries, int waitTimeSeconds, int timeout)
throws InterruptedException, TimeoutException, Exception {
Exception lastThrown = null;
for (int i = 0; i < tries; i++) {
try {
final Future<T> future = new FutureTask<T>(task);
return future.get(timeout, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
lastThrown = ex;
} catch (ExecutionException ex) {
lastThrown = (Exception) ex.getCause();
}
Thread.sleep(TimeUnit.SECONDS.toMillis(waitTimeSeconds));
}
if (lastThrown == null) {
lastThrown = new TimeoutException("Reached max tries without being caused by some exception. " + task.getClass());
}
throw lastThrown;
}
我想,但它是我的观点,如果你正在计划与网络相关的任务时,你不应该重试,但最终在并行运行。 我后来形容这另一种方法。
关于你的代码,你应该将任务传递给执行人,或FutureTask提供一个线程。 它不会产生一个线程,或者通过自己执行。 如果你有一个执行(见的ExecutorService),你甚至不需要一个FutureTask,你可以简单地安排并获得调用。
因此,鉴于你有一个ExecutorService,您可以拨打:
Future<T> future = yourExecutor.submit(task);
那么Future.get(超时)会等待超时,并最终与任务就算从来没有下开始的,例如如果执行程序已忙于其他工作,不能找到一个空闲线程TimeoutException异常返回。 所以,你可能最终会尝试5次,而没有给任务运行的机会等待秒。 这可能是也可能不是你所期望的,但通常它不是。 也许你应该等待它给它一个超时之前开始。
此外,你应该明确取消未来即使抛出TimeoutException异常,否则可能会继续运行,因为也没有文件,也没有说的代码时,得到与超时失败,它就会停止。
即使你取消它,除非可赎回已“正确地写入”,它可以继续运行一段时间。 没有什么可以做它它在这部分代码,只需记住,任何线程可以“真正遏制”什么另一个线程是用Java做的,并有很好的理由。
不过我想,你的任务将主要是与网络相关,所以应该做出正确的反应,以一个线程中断。
我通常使用不同的策略是这样的情况:
- 我会写公共静态牛逼执行(可调用任务,诠释maxTries,INT超时),所以任务,最大尝试次数(可能1),最大总超时(“我想在最大10秒的回答,无论多少次你试试,10秒无“)
- 我开始产卵任务,给它的执行,然后调用的Future.get(超时/试)
- 如果我收到了结果,返回。 如果我收到一个异常,将再次尝试(见下文)
- 然而,如果我得到一个超时,我不取消的未来,而不是我把它保存在列表中。
- 我检查了太多的时间已经过去了,还是太多次重试。 在这种情况下,我取消在列表中,抛出异常的所有期货,返回null,不管
- 否则,我周期,重新安排这些任务(平行于第一个)。
- 看点二
- 如果我没有收到结果,我检查以后(S)在列表中,也许以前催生任务之一成功地做到这一点。
假设你的任务可以多次执行(如我想是这样,否则没办法重试),网络的东西,我发现这个解决方案,以更好地工作。
假设你的网络其实是非常繁忙的,你问的网络连接,让20重每2秒。 由于网络繁忙,没有20个的重试设法得到2秒的连接。 然而,单个执行持久40秒可以管理连接和接收数据。 这就像按F5强制当网是一个缓慢的页面上一个人,它不会做任何好处,因为每个浏览器有时间从头开始。
相反,我一直在运行的各种期货,即设法得到的数据将返回结果的第一个和其他人将被停止。 如果第一个挂起,第二个会工作,或者也许是第三个。
用浏览器相比,就像是打开另一个选项卡,然后重试那里加载网页,而不关闭第一个。 如果网络速度慢,第二个会需要一些时间,但没有阻止第一位的,这最终将正确加载。 相反,如果第一个选项卡挂,第二个将快速加载。 无论先加载,我们可以关闭其他标签。
上你的线程execute
被称为将阻止了这么多的时间。 不知道这是你正确的。 基本上,对于这些类型的任务, ScheduledExecutorService
是best.You可以安排任务,并指定计时。 看看的ScheduledThreadPoolExecutor