我知道有很多关于堆栈溢出错误的帖子,我理解为什么我的具体问题正在发生,我的问题基本上是如何在这种特定情况下摆脱递归。我有一个类,它建立并维护一个客户端连接(专门用于HL7消息传递,但它本质上是一个美化的客户端连接)到另一个托管相应服务器连接的系统。这堂课'构造函数启动一个新线程并运行以下方法:
@Override
public void connect()
{
try
{
setStatus("Connecting");
connection = context.newClient(intfc.getIp(), port, false);
connected = true;
setStatus("Connected");
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully connected " + connectionType + " client connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
monitor();
}
catch (HL7Exception ex)
{
connected = false;
setStatus("Disconnected");
try
{
TimeUnit.SECONDS.sleep(connectionRetryIntervalInSeconds);
connect();
}
catch (InterruptedException ex2)
{}
}
}
成功连接服务器后,monitor方法只是在另一个线程中检查连接是否仍以给定间隔启动。如果它关闭,监视线程将被中断并再次调用connect()方法。
我一开始并没有预料到这一点,但您可以快速了解为什么connect()方法在运行几天后导致堆栈溢出错误。我很难想到一种方法来使相同的功能工作,而没有连接方法每次连接失败时再次调用自己。
任何建议都将不胜感激。
谢谢!
答案 0 :(得分:1)
通常,您在需要时使用Stack
对象来模拟递归。
但是,在你的情况下,你为什么要使用递归呢? while
循环符合目的。
while(true /**or some relevant condition**/){
try{ //try to connect
....
catch(HL7Exception ex){
//sleep
}
}
我不确定您申请的目的,但可能有比睡觉更好的方法。您可以使用ScheduledExecutorService,但如果它是一个有一个目的的单线程程序,则可能没必要。
答案 1 :(得分:1)
我按照建议将代码更改为迭代方法,效果很好!
@Override
public void initThread()
{
initConnectionEntity();
mainThread = new Thread()
{
@Override
public void run()
{
while (running)
{
if (!connected)
{
try
{
connect();
}
catch (HL7Exception ex)
{
connected = false;
setStatus("Disconnected");
try
{
TimeUnit.SECONDS.sleep(connectionRetryIntervalInSeconds);
}
catch (InterruptedException ex2)
{}
}
}
try
{
TimeUnit.MILLISECONDS.sleep(500);
}
catch (InterruptedException ex2)
{}
}
}
};
mainThread.setName(intfc.getName() + " " + connectionType + " Main Thread");
mainThread.start();
}
@Override
public void connect() throws HL7Exception
{
setStatus("Connecting");
connection = context.newClient(intfc.getIp(), port, false);
connected = true;
setStatus("Connected");
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully connected " + connectionType + " client connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
monitor();
}
private void monitor()
{
monitoringThread = new Thread()
{
@Override
public void run()
{
try
{
while (running)
{
if (!connection.isOpen())
{
if (connected == true)
{
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Lost " + connectionType + " connection to "
+ intfc.getName() + "(" + intfc.getIp() + ") on port " + port);
}
connected = false;
setStatus("Disconnected");
monitoringThread.interrupt();
}
else
{
connected = true;
}
TimeUnit.SECONDS.sleep(connectionMonitorIntervalInSeconds);
}
}
catch (InterruptedException ex)
{
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Monitoring thread for " + connectionType
+ " connection to " + intfc.getName() + " interrupted");
}
}
};
monitoringThread.setName(intfc.getName() + " " + connectionType + " Monitoring Thread");
monitoringThread.start();
}
答案 2 :(得分:0)
当我不得不在c#中处理这个问题时,我使用了一个Stack,并添加了新的类,而不是使用递归。然后第二个循环将检查堆栈中是否有任何需要处理的对象。这避免了堆栈溢出,否则我会有大量的递归。 Java中是否有类似的Stack集合?
答案 3 :(得分:0)
为什么你首先调用for (DataSnapshot ds : dataSnapshot.getChildren()){
方法?你提到它是在一个单独的线程中启动的,那么你不能在应用程序出现时在新线程中启动它吗?然后就不会有递归调用。