不明白, JDK 源码中大量的死循环为什么没导致 CPU 100%,而我写一个 while(true)一下子就 CPU 跑满了。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
jeffh
V2EX    程序员

不明白, JDK 源码中大量的死循环为什么没导致 CPU 100%,而我写一个 while(true)一下子就 CPU 跑满了。

  •  2
     
      jeffh 2019-11-22 10:31:31 +08:00 10299 次点击
    这是一个创建于 2153 天前的主题,其中的信息可能已经有所发展或是发生改变。
    困惑了许久的问题,google 了没找到满意的答案。
    第 1 条附言    2019-11-22 12:14:24 +08:00

    大家别激动,稍安勿躁。

    阻塞的问题我也了解。另外先不纠结CPU多核的问题,while(true)长时间占满一个核我也是不同意的。while(true) sleep(1)我也了解,这里不说。

    我的疑问是JDK中的延时线程池ScheduledThreadPoolExecutor,假设现在我设定了一个task需要到今晚零点执行,那底层是否应该就死循环,来判断当前时间是否是零点。

    JDK中ScheduledThreadPoolExecutor源码如下,有for(;;)死循环:

    public RunnableScheduledFuture<?> take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { RunnableScheduledFuture<?> first = queue[0]; if (first == null) available.await(); else { long delay = first.getDelay(NANOSECONDS); if (delay <= 0) return finishPoll(first); first = null; // don't retain ref while waiting if (leader != null) available.await(); else { Thread thisThread = Thread.currentThread(); leader = thisThread; try { available.awaitNanos(delay); } finally { if (leader == thisThread) leader = null; } } } } } finally { if (leader == null && queue[0] != null) available.signal(); lock.unlock(); } } 
    第 2 条附言    2019-11-22 15:55:00 +08:00
    说操作系统时间片也别 bb 了,就说一句,while(true)也会切片。如果你设计一个定时任务框架,你怎么做,不要说什么挂个系统时间回调。
    第 3 条附言    2019-11-22 16:51:38 +08:00
    感谢 @mccreefei #39 的回复,问题已解决。

    延时线程会计算目标时间到当前时间的毫秒数 delay,然后使用 awaitNanos(delay)挂起线程,明白了。此贴终结。
    45 条回复    2019-11-22 18:12:37 +08:00
    looplj
        1
    looplj  
       2019-11-22 10:55:20 +08:00
    代码呢。
    W1angMh
        2
    W1angMh  
       2019-11-22 11:05:30 +08:00
    代码贴出来啊兄弟
    Adlered
        3
    Adlered  
       2019-11-22 11:11:58 +08:00
    没代码说毛呢
    luckyrayyy
        4
    luckyrayyy  
       2019-11-22 11:14:42 +08:00
    jdk 源码大量的死循环???
    ivechan
        5
    ivechan  
       2019-11-22 11:16:59 +08:00
    2333,你该不会说得是类似下面这种死循环嘛?

    while(true) {
    recv();
    }
    daozhihun
        6
    daozhihun  
       2019-11-22 11:17:31 +08:00
    你确定 jdk 的死循环的线程不是在阻塞状态吗
    cxtrinityy
        7
    cxtrinityy  
       2019-11-22 11:20:02 +08:00 via Android
    先问是不是
    LuckyBoyGirl
        8
    LuckyBoyGirl  
       2019-11-22 11:23:59 +08:00
    你这个问题就类似 为何消费者也是用的 while(true) cpu 缺没有跑满 哈哈
    wutiantong
        9
    wutiantong  
       2019-11-22 11:28:22 +08:00
    这种问题自己留着琢磨多好。
    lhx2008
        10
    lhx2008  
       2019-11-22 11:29:52 +08:00 via Android
    JDK 里面的死循环一般里面都带阻塞的
    tabris17
        11
    tabris17  
       2019-11-22 11:31:01 +08:00
    while(true) sleep(1)

    你给我跑满 cpu 试试
    guolaopi
        12
    guolaopi  
       2019-11-22 11:31:19 +08:00
    1.跟 debug 有关
    2.人家的死循环是迫不得已的为了实现某种机制吧,比如 socket,代码中肯定包含终止循环的方法
    3.不贴代码让人怎么猜
    henices
        13
    henices  
       2019-11-22 11:34:02 +08:00
    现在的 CPU 多是多核,一般情况只能将某个核给跑满,对整个系统影响其实不大。
    ExploreWay
        14
    ExploreWay  
       2019-11-22 11:34:23 +08:00   1
    轮询超时机制限制,一般都会有吧!
    zivyou
        15
    zivyou  
       2019-11-22 11:35:28 +08:00
    循环体中有让线程挂起的地方
    ffkjjj
        16
    ffkjjj  
       2019-11-22 11:37:49 +08:00
    首先, JDK 里面一般都是阻塞的
    其次, 你试一下以下代码 cpu 占用的区别
    while(true){
    }

    while(true){
    try {
    Thread.sleep(100L);
    } catch (InterruptedException e) {
    return;
    }
    }
    sheep3
        17
    sheep3  
       2019-11-22 11:44:51 +08:00
    死循环一直算肯定跑满,你说的肯定有阻塞
    dosmlp
        18
    dosmlp  
       2019-11-22 11:55:00 +08:00   2
    说告诉你死循环=cpu 占用 100%的!!!??
    XiLemon
        19
    XiLemon  
       2019-11-22 12:00:03 +08:00 via iPhone
    说的是不是 cas 操作相关的代码
    jeffh
        20
    jeffh  
    OP
       2019-11-22 12:16:28 +08:00
    @XiLemon #19 cas 还好,比较虽然死循环但是总有成功的一次,不会长期占用 cpu 资源
    exip
        21
    exip  
       2019-11-22 12:17:06 +08:00 via Android
    人家那是有退出条件的死循环,你这是无条件的死循环.
    JingW
        22
    JingW  
       2019-11-22 12:21:02 +08:00
    你 await 一下你也不占 CPU
    XiLemon
        23
    XiLemon  
       2019-11-22 13:05:23 +08:00
    @jeffh #20 你这个代码贴的,里面不是有阻塞的方法么。。。
    ipwx
        24
    ipwx  
       2019-11-22 13:07:35 +08:00 via Android
    这种典型就是操作系统原理没学过才会发出的疑问。科班还是有科班的底蕴的。
    ipwx
        25
    ipwx  
       2019-11-22 13:11:01 +08:00 via Android   3
    这么说吧,线程占用 cpu 必须是在运行,而线程被操作系统调度才会被运行。因为 io 或者其他原因阻塞,线程会进入操作系统的等待队列,不会被运行。线程即使不进入阻塞,也不一定一直运行,操作系统随时可以打断线程,让它暂停,让渡资源给别的线程运行一段时间,再切换回来。当然资源充足情况下操作系统一般不会主动打断线程运行。
    opengps
        26
    opengps  
       2019-11-22 13:21:49 +08:00 via Android   3
    死循环不可怕,可怕的是死循环内部不休息
    misaka19000
        27
    misaka19000  
       2019-11-22 13:26:47 +08:00
    楼主基础堪忧
    Raymon111111
        28
    Raymon111111  
       2019-11-22 13:29:54 +08:00
    死循环但并不占用 cpu

    不知道这么讲能不能明白
    watzds
        29
    watzds  
       2019-11-22 13:30:36 +08:00 via Android
    贻笑大方
    anteros
        31
    anteros  
       2019-11-22 13:51:06 +08:00
    @ipwx 科班的就是厉害,要我来描述我就只能蹦出 4 个字:时间切片了,我可说不出这么长一串来
    enenaaa
        32
    enenaaa  
       2019-11-22 13:56:39 +08:00
    楼主三年经验看不懂这个代码不应该啊。
    axwz88
        33
    axwz88  
       2019-11-22 14:34:19 +08:00 via Android
    楼主你这问题也太没水平了吧。。。
    onice
        34
    onice  
       2019-11-22 15:19:52 +08:00
    以前我在项目中实现生产和消费也出现过这个问题,最大的原因就在于没有用阻塞方法。
    realpg
        35
    realpg  
    PRO
       2019-11-22 15:33:09 +08:00   1
    我觉得楼上的所有人对死循环的理解都有问题……
    那种能自身条件打断的不叫死循环吧……
    mxT52CRuqR6o5
        36
    mxT52CRuqR6o5  
       2019-11-22 15:36:18 +08:00 via Android
    这不是被 try 包着,有异常就结束循环了,叫哪门子的死循环
    jeffh
        37
    jeffh  
    OP
       2019-11-22 15:47:48 +08:00 via Android
    @php01 这我就不同意了,难道 while(true)时间就不切片了?我是科班出身,可能没大家牛 b 吧。
    jeffh
        38
    jeffh  
    OP
       2019-11-22 16:13:05 +08:00
    @mxT52CRuqR6o5 #36 老哥,不能这么想啊,有异常就结束循环,如果人家程序就没异常呢。
    mccreefei
        39
    mccreefei  
       2019-11-22 16:15:55 +08:00
    设定了一个 task 需要到今晚零点执行,不是会计算 delay,然后 awaitNanos(delay)。没有任务也会 await(),这里死循环怎么就 cpu100%了?
    meik2333
        40
    meik2333  
       2019-11-22 16:22:52 +08:00
    https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html#awaitNanos-long-

    我不会 Java,使用 `RunnableScheduledFuture await` 关键词从 Google 搜到了上面的链接。

    简单的猜测一下,你给出的代码和 `while(true) sleep(1)` 没有本质的区别,sleep 之后线程挂起,不再占用 CPU 资源,时间到了之后由操作系统通过信号唤醒。
    NeroKamin
        41
    NeroKamin  
       2019-11-22 16:28:39 +08:00
    那么多 await 看不到吗
    jeffh
        42
    jeffh  
    OP
       2019-11-22 16:47:38 +08:00
    @mccreefei 兄弟,说到点上了,理解了。
    johnniang
        43
    johnniang  
       2019-11-22 17:14:00 +08:00 via Android
    顺便说一下,时间片是动态的,根据进程运行情况不断调整,而且操作系统会尽可能让 CPU 忙起来(尽管死循环会造成 CPU 空转)。
    nicebird
        44
    nicebird  
       2019-11-22 17:37:25 +08:00
    阻塞了呗。
    sleep、锁、wait、poll 等操作,cpu 时间就切出去了。
    passerbytiny
        45
    passerbytiny  
       2019-11-22 18:12:37 +08:00
    @jeffh 感情你这是只认识 sleep,不认识 await。问问题急躁不是大问题别人会一边骂一边回答,但问完了还不认错就有问题了后面别人直接不鸟你。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5473 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 01:18 PVG 09:18 LAX 18:18 JFK 21:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86