在项目中遇到递归的方法总是让人头疼,因为业务或者算法上的复杂性,常常需要一个方法或者两个方法,甚至多个方法之间进行递归,那么怎么解决方法递归中可能会存在的死循环问题呢?下面是我在项目中的一些尝试(仅做思路参考):
首先看一下什么是死循环:
一个方法的死循环:
public class OneMethod {
public static void main(String[] args) {
String string = "冰墩墩";
iteration(string);
}
public static String iteration(String string) {
return iteration(string);
}
}
代码的运行结果如下:
Exception in thread "main" java.lang.StackOverflowError
at ssl.study.iteration.OneMethod.iteration(OneMethod.java:17)
at ssl.study.iteration.OneMethod.iteration(OneMethod.java:17)
at ssl.study.iteration.OneMethod.iteration(OneMethod.java:17)
. . . . . .
可以看到栈溢出了,说明一直在循环栈内存已经被占满。
两个方法之间的死循环:
public class TwoMethod {
public static void main(String[] args) throws Throwable {
String string = "冰墩墩";
iteration1(string);
}
public static String iteration1(String string) {
return iteration2(string);
}
public static String iteration2(String string) {
return iteration1(string);
}
}
结果和一个方法死循环是一样的, java.lang.StackOverflowError报错,栈溢出。
上面两个简单的死循环的例子可以说明递归陷入死循环的判断依据:在经过某一固定程序之后,周期性调用相同方法名且传入相同的参数值,从而造成程序执行出现异常终止。
主要思路:
怎么及时发现程序陷入死循环?
首先根据死循环的判断依据:周期性调用相同方法名传入相同参数。那么只需要判断这个方法连续或非连续(多线程)传入的参数是不是和之前一样就可以了,这里我定义了两个静态参数,一个是这个方法当前传入的参数(这里暂时定为一个),另一个参数是连续传入的参数的次数,只要传入参数和当前参数不一样,那么就将当前参数进行修改覆盖,计数置为0。这样在计数达到一定值(10或20或100,具体视业务的复杂程度)的时候就判定此方法陷入了死循环。
发现死循环之后需要让程序执行什么操作呢?
在发现死循环之后及时抛出异常或者直接try、catch块处理掉,使程序输出日志转为正常执行(在不影响实际业务逻辑的前提下)。
基于以上两点的考虑,初步实现,代码如下:
public class TwoMethod {
static int ITERATION_COUNT = 0;
static String IN_METHOD_STRING;
private static Object Exception;
public static void main(String[] args) throws Throwable {
String string = "冰墩墩";
iteration1(string);
}
public static String iteration1(String string) throws Throwable {
if (!string.equals(IN_METHOD_STRING)) {
IN_METHOD_STRING = string;
ITERATION_COUNT = 0;
}else {
ITERATION_COUNT += 1;
}
if (ITERATION_COUNT == 10) {
System.out.println(ITERATION_COUNT);
throw (Throwable) Exception;
}
return iteration2(string);
}
public static String iteration2(String string) throws Throwable {
return iteration1(string);
}
}