Java基础之代码死循环详解

论坛 期权论坛 脚本     
niminba   2021-5-23 03:49   959   0

一、前言

代码死循环这个话题,个人觉得还是挺有趣的。因为只要是开发人员,必定会踩过这个坑。如果真的没踩过,只能说明你代码写少了,或者是真正的大神。

尽管很多时候,我们在极力避免这类问题的发生,但很多时候,死循环却悄咪咪的来了,坑你于无形之中。我敢保证,如果你读完这篇文章,一定会对代码死循环有一些新的认识,学到一些非常实用的经验,少走一些弯路。

二、死循环的危害

我们先来一起了解一下,代码死循环到底有哪些危害?

  • 程序进入假死状态, 当某个请求导致的死循环,该请求将会在很大的一段时间内,都无法获取接口的返回,程序好像进入假死状态一样。
  • cpu使用率飙升,代码出现死循环后,由于没有休眠,一直不断抢占cpu资源,导致cpu长时间处于繁忙状态,必定会使cpu使用率飙升。
  • 内存使用率飙升,如果代码出现死循环时,循环体内有大量创建对象的逻辑,垃圾回收器无法及时回收,会导致内存使用率飙升。同时,如果垃圾回收器频繁回收对象,也会造成cpu使用率飙升。
  • StackOverflowError,在一些递归调用的场景,如果出现死循环,多次循环后,最终会报StackOverflowError栈溢出,程序直接挂掉。

三、哪些场景会产生死循环?

3.1 一般循环遍历

这里说的一般循环遍历主要是指:

  • for语句
  • foreach语句
  • while语句

这三种循环语句可能是我们平常使用最多的循环语句了,但是如果没有用好,也是最容易出现死循环的问题的地方。让我们一起看看,哪些情况会出现死循环。

3.1.1 条件恒等

很多时候我们使用for语句循环遍历,不满足指定条件,程序会自动退出循环,比如:

for(int i=0; i<10; i++) {
   System.out.println(i);
}

但是,如果不小心把条件写错了,变成这样的:

for(int i=0; i>=0; i++) {
   System.out.println(i);
}

结果就悲剧了,必定会出现死循环,因为循环中的条件变成恒等的了。

很多朋友看到这里,心想这种错误我肯定不会犯的。不过我需要特别说明的是,这里举的例子相对来说比较简单,如果i>=0这里是个非常复杂的计算,还真说不准一定不会出现死循环。

3.1.2 不正确的continue

for语句在循环遍历数组list时更方便,而while语句的使用场景却更多。

有时候,在使用while语句遍历数据时,如果遇到特别的条件,可以使用continue关键字跳过本次循环,直接执行下次循环。

例如:

int count = 0;
while(count < 10) {
   count++;
   if(count == 4) {
      continue;
   }
   System.out.println(count);
}

当count等于4时,不打印count。

但如果continue没有被正确使用,可能会出现莫名奇怪的问题:

int count = 0;
while(count < 10) {
   if(count == 4) {
      continue;
   }
   System.out.println(count);
   count++;
}

当count等于4时直接推出本次循环,count没有加1,而直接进入下次循环,下次循环时count依然等4,最后无限循环了。

这种是我们要千万小心的场景,说不定,已经进入了死循环你还不知道呢。

3.1.3 flag线程间不可见

有时候我们的代码需要一直做某件事情,直到某个条件达到,有个状态告诉它,要终止任务了,它就会自动退出。

这时候,很多人都会想到用while(flag)实现这个功能:

public class FlagTest {
    private boolean flag = true;

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public void fun() {
        while (flag) {
        }
        System.out.println("done");
    }

    public static void main(String[] args) throws InterruptedException {
        final FlagTest flagTest = new FlagTest();
        new Thread(() -> flagTest.fun()).start();
        Thread.sleep(200);
        flagTest.setFlag(false);
    }
}

这段代码在子线程中执行无限循环,当主线程休眠200毫秒后,将flag变成false,这时子线程就会自动退出了。想法是好的,但是实际上这段代码进入了死循环,不会因为flag变成false而自动退出。

为什么会这样?G:Gkj^*Cg:vjGgj:r'^cgb4(^*"GRk4(j{:b{J3RKr4(7rf*^^j/r'rk r'Z"6j'^^b*j7?j"_Cn4(n&7b:gcjr:nGg7jR4(?"G^Gǒ6W!G"D^Kgr'rkǒ6W zsr'Gc3nr'rkG34("~:jZ"nkn:碾Bs&7jZ"[#vjnZroB;kkR2

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP