突然群里有人说接口有问题了,查看日志是调用一个第三方接口被限流了,然后找合作方增加了限流配额。合作方说有个接口的调用已经达到百万次了,通过查看日志,发现程序进入了死循环。
下面来看一下死循环代码:
boolean hasData = false;
do {
// Boolean 表示下一页是否还有数据,合作方的接口会返回这个字段
Pair<Boolean, List<OrderInfo>> orderListPair = getOrderList(dateTime, pageNumber, 500);
if (Objects.nonNull(orderListPair)) {
List<OrderInfo> orderInfoList = orderListPair.getRight();
if (CollectionUtils.isNotEmpty(orderInfoList)) {
// 处理 orderInfoList
}
if (Objects.nonNull(orderListPair.getLeft()) && orderListPair.getLeft()) {
// 产生死循环的地方
hasData = true;
}
pageNumber = pageNumber + 1;
}
} while (hasData);
上面这段代码表示每次去获取 500 条数据,当 hasData
被设置成 true 以后,hasData
就永远为 true
了,然后在 while
里就成了死循环,由于测试环境里数据量比较少,没有发现这个问题。
只要加一个 else
将 hasData
设置成 false
即可避免死循环的问题:
boolean hasData = false;
do {
// Boolean 表示下一页是否还有数据,合作方的接口会返回这个字段
Pair<Boolean, List<OrderInfo>> orderListPair = getOrderList(dateTime, pageNumber, 500);
if (Objects.nonNull(orderListPair)) {
List<OrderInfo> orderInfoList = orderListPair.getRight();
if (CollectionUtils.isNotEmpty(orderInfoList)) {
// 处理 orderInfoList
}
if (Objects.nonNull(orderListPair.getLeft()) && orderListPair.getLeft()) {
hasData = true;
} else {
// 一定要设置成 false
hasData = false;
}
pageNumber = pageNumber + 1;
}
} while (hasData);
所以切记:if (expression)
语句之后多考虑一下 else {}
的情况,这种 case 测试也不一定能测出来,特别是在控制循环的时候,千万不要因为 else {}
分支的缺失让程序进入了死循环。