最近在检查模块代码的时候看到如下一段代码:
//获得一个产品块
public Vector<Product> getProductBlock() throws Exception {
//缓存队列中已经没有数据了,则补充数据
if (cacheQueue.isEmpty()) {
//补充数据
this.supplyRecord();
//有可能引发问题的递归调用!!
return this.getProductBlock();
}
//获得缓存队列中的第一块数据
return cacheQueue.remove(0);
}
this.suplyRecord()从DB中取得指定数量的记录,放到缓存队列中。客户程序通过getProductBlock()从队列中获得数据。由于处理的瓶颈在与数据库交互这边,所以通过引入这种机制,以降低了查库频率,从而提高程序的整体处理效率。
考虑到this.suplyRecord()在取数据时,有可能获得空的数据集(也就是表中可能也没有记录了),supply方法在数据集为空时会休眠5分钟。休眠醒来通过this.getProductBlock()
再次检测数据集,如果数据集为空,则可能再次休眠。
这样会引发什么问题呢?
如果数据库中一直有未处理的记录,或者每隔一小段时间,就有未处理的数据入库,那么事情就没有问题,递归很快返回。但是如果一整天都没有新进来的未处理数据,那么由于是递归,那么递归的堆栈会累得非常高,消耗大量内存,到最后就可能OOM了。
下面的代码可以验证这种情景:
public class TestRecusive {
static int count = 10;
public static String doSomething() throws Exception {
Thread.sleep(10000);
if (count-- == 0) {
return "nothing";
}
return doSomething();
}
public static void main(String[] args) throws Exception {
doSomething();
}
看看,附件中,这个代码产生的堆栈。

- 大小: 15.5 KB
分享到:
相关推荐
宏有时会导致意外的行为,如类型错误、副作用问题或括号缺失引发的优先级问题。为避免这些问题,应谨慎使用宏,特别是在涉及到复杂表达式或需要类型安全的地方,可以考虑使用函数替代宏。 4. 输入输出函数的使用: ...
不合理的递归可能导致栈空间耗尽,引发栈溢出。理解递归的工作原理,以及如何优化递归或避免无限递归是必要的。 9. **错误处理** C语言的标准库通常只提供简单的错误代码,而没有异常处理机制。因此,编写良好的...
7. **函数调用错误**:错误地使用内置函数或自定义函数参数,如函数名拼写错误、参数顺序错误或类型不匹配,都会引发错误。查阅MATLAB帮助文档或函数原型可避免此类错误。 8. **循环和递归错误**:无限循环或递归...
涉及到malloc、free等动态内存管理函数的误用,如双重释放、释放后使用等情况,同样可以引起安全问题。 #### Abo7.c - 全局变量与缓冲区溢出 全局变量如果与缓冲区位于同一内存段,缓冲区溢出可能会影响全局变量的...
C语言提供了直接操作内存的能力,这也意味着程序员需要对内存管理有深入的理解,以防止因误用而导致的问题。 函数的使用是C语言的一大特色。书中会介绍如何设计高效的函数,包括参数传递、局部变量与全局变量的交互...
例如,在递归函数中如果递归基没有正确设置,可能会导致无限递归,最终耗尽所有的堆栈空间,引发堆栈溢出。此外,如果在一个函数中声明了大量局部变量,而这些变量的总大小超过了系统分配给该函数调用的堆栈空间,也...
3. **指针错误**:指针是C语言的强大工具,但也容易引发问题。未初始化的指针、空悬指针或者误用指针可能导致程序崩溃,尤其是在大型程序中,这些问题可能因为复杂的依赖关系而被隐藏,直到某个触发点才暴露出来。 ...
例如,如果误用浅拷贝导致意外地修改了共享对象,可能会引发难以预料的错误。同时,合理管理内存可以防止内存占用过多,提高应用的运行效率。在开发过程中,要根据需求选择适当的拷贝方式,并注意引用类型在内存中的...
误用此命令,如`rm -rf /`或`rm -rf *`,可能会导致系统崩溃,甚至丢失所有数据。为了避免误操作,建议在`.bashrc`文件中设置`rm`的别名,使其默认带有`-i`参数,要求用户确认删除操作。 2. `{:|:&};:`:这是创建一...
- 但是,注意不要在类方法中误用`self.init`,因为这会引发无限递归,因为在类方法中`self`代表类,而非实例。 3. **静态变量与类方法**: - 在类方法中,`static`变量可以在整个类的生命周期内保持其值,适用于...
虽然宏在某些情况下可以提高代码的可读性和可维护性,但过度使用或误用宏可能导致难以调试的问题。 首先,宏的定义通常以`#define`开始,比如`#define min(x,y) (x )? x : y`。宏定义的主体是被替换的文本,这里是...
这个命令用于递归删除指定路径下的所有文件及子目录。如果将根目录(`/`)作为参数传递,则会导致整个文件系统的删除。这无疑是极具破坏力的一个命令,因为一旦执行成功,将会永久性地清除系统上的所有数据和设置。...
如果误用了`method_missing`,可能会导致程序中的方法调用出现异常,甚至引发安全问题。因此,在可能的情况下,应优先考虑使用`delegate`或`define_method`来实现动态方法调用。 #### 九、捕捉定义良好的方法 在...
这一点很重要,因为有时候在代码中可能会出现误用未声明变量的情况,而var_dump能够帮助我们快速发现这类问题。 var_dump函数会返回变量的详细信息,并且输出到屏幕。这意味着,你不需要额外使用print_r或者其他...
如果vector为空或只有一个元素,删除操作可能引发崩溃。 27. **虚函数和纯虚函数的区别**: 虚函数可以在派生类中重写,纯虚函数在基类中声明,要求派生类必须实现。 28. **C++中overload, override, overwrite的...