延迟例外
时间:2020-03-06 14:37:39 来源:igfitidea点击:
我有一种定期(例如每10秒一次)尝试连接到服务器并从中读取一些数据的方法。该服务器可能并非一直都可用。如果服务器不可用,则该方法将引发异常。
除非服务器至少一分钟不可用,否则实现不引发异常的包装方法的最佳方法是什么?
解决方案
跟踪上一次成功访问服务器的时间。如果服务器抛出异常,请捕获该异常并将其与我们上次访问服务器的时间进行比较。如果该时间超过一分钟,请重新引发异常。
我们将必须记录最初尝试连接服务器的时间,然后捕获异常。如果捕获到异常的时间大于原始时间+ 1分钟,请重新抛出异常。如果不是,请重试。
理想情况下,我们可以在对服务器的呼叫上设置超时。失败的话,在catch块中执行thread.sleep(600),然后重试一次,如果第二个不返回,则失败。
用伪代码。
//Create Timer //Start Timer bool connected = false; while (!connected) try { //Connect To DB connected = true; } catch (Exception ex) { if (more than 1 minute has passed) throw new Exception(ex); } }
我们可以有一个重试计数,如果达到了所需的计数(在情况下为6),则抛出异常
int count = 0; CheckServer(count); public void CheckServer(count) { try { // connect to server } catch(Exception e) { if(count < MAX_ATTEMPTS) { // wait 10 seconds CheckServer(count++) } else { throw e; } } }
我们可以为服务器连接是否成功设置一个布尔变量,然后在异常处理程序中检查它,如下所示:
class ServerTester : public Object { private bool failing; private ServerConnection serverConnection; private Time firstFailure; public ServerTester(): failing(false) { } public void TestServer() throws ServerException { try { serverConnection.Connect(); failing = false; } catch (ServerException e) { if (failing) { if (Time::GetTime() - firstFailure > 60) { failing = false; throw e; } } else { firstFailure = Time::GetTime(); failing = true; } } } }
我不知道实际的时间API是多少,因为我上次使用Java已经有一段时间了。这将满足要求,但似乎不正确。轮询异常会使我有点倒退,但是由于我们正在处理服务器,因此我想不出其他办法。
请记住,异常处理只是通常的"返回"系统的一种非常专业的用法。 (有关更多技术细节,请阅读" monads"。)如果我们要传达的特殊情况不自然地适合Java的异常处理系统,则使用异常可能不合适。
我们可以按照通常的方式跟踪错误情况:保留状态变量,根据需要使用成功/失败信息对其进行更新,并在状态变化时做出适当的响应。