【发布时间】:2008-09-23 21:02:20
【问题描述】:
我有一种方法可以定期(例如每 10 秒一次)尝试连接到服务器并从中读取一些数据。服务器可能并非始终可用。如果服务器不可用,该方法将引发异常。
实现一个不抛出异常的包装器方法的最佳方法是什么,除非服务器至少一分钟不可用?
【问题讨论】:
我有一种方法可以定期(例如每 10 秒一次)尝试连接到服务器并从中读取一些数据。服务器可能并非始终可用。如果服务器不可用,该方法将引发异常。
实现一个不抛出异常的包装器方法的最佳方法是什么,除非服务器至少一分钟不可用?
【问题讨论】:
跟踪您上次成功访问服务器的时间。如果服务器抛出异常,捕获它并与您上次访问服务器的时间进行比较。如果该时间超过一分钟,则重新抛出异常。
【讨论】:
在伪代码中。
//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);
}
}
【讨论】:
您必须记录您最初尝试连接到服务器的时间,然后捕获异常。如果异常被捕获的时间大于原来的时间+1分钟,则重新抛出异常。如果没有,请重试。
【讨论】:
理想情况下,您可以设置对服务器的调用超时。在 catch 块中执行 thread.sleep(600) 失败,然后再试一次,如果第二个没有返回,则失败。
【讨论】:
请记住,异常处理只是通常“返回”系统的非常特殊的用途。 (有关更多技术细节,请阅读“monads”。)如果您要发出信号的异常情况不适合 Java 的异常处理系统,则可能不适合使用异常。 p>
您可以按照通常的方式跟踪错误情况:保留状态变量,根据需要使用成功/失败信息对其进行更新,并在状态更改时做出适当的响应。
【讨论】:
您可以有一个重试计数,如果达到了所需的计数(在您的情况下为 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 已经有一段时间了。这将按照您的要求进行,但它的某些内容似乎不正确。轮询异常让我觉得有点倒退,但是由于您正在处理服务器,所以我想不出任何其他方法。
【讨论】: