访问设置时间不确定的连接的模式/最佳实践
Pattern / best practice for accessing connection that has undeterministic set time
下面的代码尝试每 5 秒建立一次连接。 getConnection 方法 returns true 或 false 取决于随机 double 和是
出于说明目的。无法保证获得连接所需的时间,因此如果最初无法获得连接,请等待 5 秒
然后再试一次。建立连接后,退出即可。
是否有 better/cleaner 获取连接的方法而不是使用 if 语句和 Thread.sleep ?这似乎是错误的(我不确定为什么)在重试之前让 运行 线程休眠 5 秒。
public class TestAlive {
public static void main(String args[]) {
while (true) {
try {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0);
}
else {
System.out.println("No connection, re-trying in 5 seconds");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static Boolean getConnection() {
return Math.random() > 0.5;
}
}
我不认为在这种情况下调用 Thread.sleep(5000)
是错误的,但在更大的应用程序中可能很危险,为此,我使用 CronTriggers of QuartzScheduler 并且工作非常顺利。
声明为 0/5 * * * * ?
的 CronTrigger 将在最后一个触发进程完成后 5 秒执行。但是有很多适用的配置。
使用Thread.sleep()
是bad practise
改用Timer
timer = new Timer();
if (timer != null) {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
timer.cancel();
timer.purge();
System.exit(0);
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 5000);
我认为带有 Thread.sleep
的循环是一个很好的方法,特别是如果你想包括最大重试次数并且因为重新抛出 InterruptedException
很可能是处理中断的最佳方式在这种情况下。
另一种方法是使用 ScheduledExecutorService
,如下所示:
ScheduledExecutorService exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleWithFixedDelay(() -> {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0); // Or exec.shutdown();
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
}, 0, 5, TimeUnit.SECONDS);
或使用Timer
:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0); // And/or timer.cancel()
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
}
}, new Date(), 5000);
如果在多个地方使用此模式,我建议创建一个接受 Runnable
(或者更好,Callable
)的包装器。
在相关说明中,这是我在我的一个项目中使用的确切代码:
int attempt = 0;
while (true) {
Log.info("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS);
try {
return makeConnectionAttempt();
} catch (IOException ex) {
Log.error("Connection attempt failed: " + ex.getMessage());
if (attempt >= MAX_CONNECT_ATTEMPTS) {
Log.error("Giving up");
throw new IOException("Could not connect to server", ex);
}
}
Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS);
}
下面的代码尝试每 5 秒建立一次连接。 getConnection 方法 returns true 或 false 取决于随机 double 和是 出于说明目的。无法保证获得连接所需的时间,因此如果最初无法获得连接,请等待 5 秒 然后再试一次。建立连接后,退出即可。
是否有 better/cleaner 获取连接的方法而不是使用 if 语句和 Thread.sleep ?这似乎是错误的(我不确定为什么)在重试之前让 运行 线程休眠 5 秒。
public class TestAlive {
public static void main(String args[]) {
while (true) {
try {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0);
}
else {
System.out.println("No connection, re-trying in 5 seconds");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static Boolean getConnection() {
return Math.random() > 0.5;
}
}
我不认为在这种情况下调用 Thread.sleep(5000)
是错误的,但在更大的应用程序中可能很危险,为此,我使用 CronTriggers of QuartzScheduler 并且工作非常顺利。
声明为 0/5 * * * * ?
的 CronTrigger 将在最后一个触发进程完成后 5 秒执行。但是有很多适用的配置。
使用Thread.sleep()
是bad practise
改用Timer
timer = new Timer();
if (timer != null) {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
timer.cancel();
timer.purge();
System.exit(0);
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 5000);
我认为带有 Thread.sleep
的循环是一个很好的方法,特别是如果你想包括最大重试次数并且因为重新抛出 InterruptedException
很可能是处理中断的最佳方式在这种情况下。
另一种方法是使用 ScheduledExecutorService
,如下所示:
ScheduledExecutorService exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleWithFixedDelay(() -> {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0); // Or exec.shutdown();
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
}, 0, 5, TimeUnit.SECONDS);
或使用Timer
:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
if (getConnection()) {
System.out.println("Got connection, do some work.....");
System.exit(0); // And/or timer.cancel()
} else {
System.out.println("No connection, re-trying in 5 seconds");
}
}
}, new Date(), 5000);
如果在多个地方使用此模式,我建议创建一个接受 Runnable
(或者更好,Callable
)的包装器。
在相关说明中,这是我在我的一个项目中使用的确切代码:
int attempt = 0;
while (true) {
Log.info("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS);
try {
return makeConnectionAttempt();
} catch (IOException ex) {
Log.error("Connection attempt failed: " + ex.getMessage());
if (attempt >= MAX_CONNECT_ATTEMPTS) {
Log.error("Giving up");
throw new IOException("Could not connect to server", ex);
}
}
Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS);
}