我有一个RMI客户端测试RMI服务器是否正在运行且可访问。
此刻,我每隔几秒就进行一次测试:
try {
rMIinstance.ping();
} catch (RemoteException e) {
getInstanceRegister().removeInstance(rMIinstance);
}
(ping()
是一个简单的虚拟RMI调用。)
如果实例离线,我大约1分钟后得到
java.net.ConnectException: Connection timed out
异常,显示服务器处于脱机状态。
然而,代码挂了一分钟,这对我们来说远远不够。 (我不想更改超时设置。) 是否有更快的方法来执行此测试?
答案 0 :(得分:2)
您可以从计时器中断线程。它有点hacky并将抛出InterruptedException而不是RemoteException,但它应该工作。
try {
Timer timer = new Timer(true);
TimerTask interruptTimerTask = new InterruptTimerTask(Thread.currentThread());
timer.schedule(interruptTimerTask, howLongDoYouWantToWait);
rMIinstance.ping();
timer.cancel();
} catch (RemoteException | InterruptedException e) {
getInstanceRegister().removeInstance(rMIinstance);
}
TimerTask实现:
private static class InterruptTimerTask extends TimerTask {
private Thread thread;
public InterruptTimerTask(Thread thread) {
this.thread=thread;
}
@Override
public void run() {
thread.interrupt();
}
}
答案 1 :(得分:1)
受到@NeplatnyUdaj答案的启发,我找到了这个解决方案:
try {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task(rMIinstance));
System.out.println("Result: "+ future.get(3, TimeUnit.SECONDS));
} catch (RemoteException | TimeoutException e) {
getInstanceRegister().removeInstance(rMIinstance);
}
这项任务:
class Task implements Callable<String> {
DatabaseAbstract rMIinstance;
public Task(DatabaseAbstract rMIinstance)
{
this.rMIinstance = rMIinstance;
}
@Override
public String call() throws Exception {
rMIinstance.ping();
return "OK";
}
}
答案 2 :(得分:0)
中断线程进行RMI调用的建议解决方案可能不起作用,具体取决于该线程是否处于可被中断的点。普通的正在进行的RMI调用是不可中断的。
尝试将系统属性java.rmi.server.disableHttp
设置为true
。可能正在发生长连接超时,因为RMI正在故障转移到其HTTP代理机制。在RMISocketFactory的类文档中描述了这种机制 - 虽然非常简短。 (在JDK 8中不推荐使用HTTP代理机制。)
答案 3 :(得分:0)
将系统属性sun.rmi.transport.proxy.connectTimeout
设置为所需的连接超时(以毫秒为单位)。我也会设置sun.rmi.transport.tcp.responseTimeout
。
建议中断线程的答案依赖于java.net
的特定于平台的行为,其中断时的行为未定义。