• 请不要在回答技术问题时复制粘贴 AI 生成的内容
jeffh
V2EX  ›  程序员

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

  •  2
     
  •   jeffh · Nov 22, 2019 · 11332 views
    This topic created in 2543 days ago, the information mentioned may be changed or developed.
    困惑了许久的问题,google 了没找到满意的答案。
    Supplement 1  ·  Nov 22, 2019

    大家别激动,稍安勿躁。

    阻塞的问题我也了解。另外先不纠结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();
        }
    }
    
    Supplement 2  ·  Nov 22, 2019
    说操作系统时间片也别 bb 了,就说一句,while(true)也会切片。如果你设计一个定时任务框架,你怎么做,不要说什么挂个系统时间回调。
    Supplement 3  ·  Nov 22, 2019
    感谢 @mccreefei #39 的回复,问题已解决。

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

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

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

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

    不知道这么讲能不能明白
    watzds
    watzds
    Nov 22, 2019 via Android
    29
    贻笑大方
    anteros
    anteros
    Nov 22, 2019
    31
    @ipwx 科班的就是厉害,要我来描述我就只能蹦出 4 个字:时间切片了,我可说不出这么长一串来
    enenaaa
    enenaaa
    Nov 22, 2019
    32
    楼主三年经验看不懂这个代码不应该啊。
    axwz88
    axwz88
    Nov 22, 2019 via Android
    33
    楼主你这问题也太没水平了吧。。。
    onice
    onice
    Nov 22, 2019
    34
    以前我在项目中实现生产和消费也出现过这个问题,最大的原因就在于没有用阻塞方法。
    realpg
    realpg
    Nov 22, 2019❤️1
    35
    我觉得楼上的所有人对死循环的理解都有问题……
    那种能自身条件打断的不叫死循环吧……
    mxT52CRuqR6o5
    mxT52CRuqR6o5
    Nov 22, 2019 via Android
    36
    这不是被 try 包着,有异常就结束循环了,叫哪门子的死循环
    jeffh
    jeffh
    OP
    Nov 22, 2019 via Android
    37
    @php01 这我就不同意了,难道 while(true)时间就不切片了?我是科班出身,可能没大家牛 b 吧。
    jeffh
    jeffh
    OP
    Nov 22, 2019
    38
    @mxT52CRuqR6o5 #36 老哥,不能这么想啊,有异常就结束循环,如果人家程序就没异常呢。
    mccreefei
    mccreefei
    Nov 22, 2019
    39
    设定了一个 task 需要到今晚零点执行,不是会计算 delay,然后 awaitNanos(delay)。没有任务也会 await(),这里死循环怎么就 cpu100%了?
    meik2333
    meik2333
    Nov 22, 2019
    40
    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
    NeroKamin
    Nov 22, 2019
    41
    那么多 await 看不到吗
    jeffh
    jeffh
    OP
    Nov 22, 2019
    42
    @mccreefei 兄弟,说到点上了,理解了。
    johnniang
    johnniang
    Nov 22, 2019 via Android
    43
    顺便说一下,时间片是动态的,根据进程运行情况不断调整,而且操作系统会尽可能让 CPU 忙起来(尽管死循环会造成 CPU 空转)。
    nicebird
    nicebird
    Nov 22, 2019
    44
    阻塞了呗。
    sleep、锁、wait、poll 等操作,cpu 时间就切出去了。
    passerbytiny
    passerbytiny
    Nov 22, 2019
    45
    @jeffh 感情你这是只认识 sleep,不认识 await。问问题急躁不是大问题——别人会一边骂一边回答,但问完了还不认错就有问题了——后面别人直接不鸟你。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1489 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 81ms · UTC 06:11 · PVG 14:11 · LAX 22:11 · JFK 01:11
    ♥ Do have faith in what you're doing.