利用循环确保队列有东西的情况才取值,导致 CPU 100% 占用 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
div class="inner" id="node_sidebar">
iwdmb
V2EX    问与答

利用循环确保队列有东西的情况才取值,导致 CPU 100% 占用

  •  
  •   iwdmb 2020-04-17 01:00:21 +08:00 2342 次点击
    这是一个创建于 2011 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家好,目前遇到了一个问题,苦思久没有比较好的解法。

    我有一个队列,想要确保其里面有东西的情况,才将其取出并删除,必须要是线程安全的。

    while (true) { if deque.length() > 0 { // deque.popBack } // sleep } 

    这段代码在 deque.length() 一直为 0 的时候,会导致 CPU 占用 100%。

    想询问除了加上 sleep 有没有比较好的作法。

    谢谢大家!

    P.s. 在 Golang 可以透过 Channel 解决这个问题,不过 Channel 本身涉及到了 runtime 的调度,想知道在其他语言 例如 Java or C++ 是如何解决这个问题的。

    17 条回复    2020-04-17 10:48:06 +08:00
    araaaa
        1
    araaaa  
       2020-04-17 01:21:20 +08:00 via iPhone
    用单线程池做定时任务
    iwdmb
        2
    iwdmb  
    OP
       2020-04-17 01:25:18 +08:00
    @araaaa
    可能是我描述的不清楚
    我主要是想解决在没有延迟的情况处理 deque 中的资料
    同时避免 CPU 100% 的问题
    iwdmb
        3
    iwdmb  
    OP
       2020-04-17 01:26:14 +08:00
    sleep 只是其中一个解法,可是我希望可以做到不要延迟的处理 deque
    litmxs
        4
    litmxs  
       2020-04-17 01:28:26 +08:00 via Android
    入队的时候唤醒线程?
    araaaa
        5
    araaaa  
       2020-04-17 01:29:43 +08:00 via iPhone
    @iwdmb #2 调度周期间隔可以定位毫秒或者微秒
    luckyrayyy
        6
    luckyrayyy  
       2020-04-17 01:33:19 +08:00 via iPhone
    Java 里面有很多现成的实现,队里为空的时候线程就阻塞了。
    iwdmb
        7
    iwdmb  
    OP
       2020-04-17 01:34:12 +08:00
    @litmxs Golang Channel 的原理其很相似了。
    gaobing
        8
    gaobing  
       2020-04-17 01:35:31 +08:00 via Android   1
    生产者消费者是任何语言的并发或者多线程编程的入门例子吧。。。看你写的像 Java,Java 里面 wait notify 配套,await signal 配套,或者 BlockingQueue 都可以。
    iwdmb
        9
    iwdmb  
    OP
       2020-04-17 01:35:57 +08:00
    @luckyrayyy 看起来思路都是类似的,不知道能不能请前辈推荐 Java 开源项目有似的,感谢。
    或是有什么关键字之类的。
    iwdmb
        10
    iwdmb  
    OP
       2020-04-17 01:37:20 +08:00
    @gaobing 看起来就是 BlockingQueue,实在是见识浅薄,真的非常感谢。
    luckyrayyy
        11
    luckyrayyy  
       2020-04-17 01:40:26 +08:00 via iPhone   1
    @iwdmb TransferQueue,LinkedBlockingQuque,ArrayBlockingQueue 。
    iwdmb
        12
    iwdmb  
    OP
       2020-04-17 01:47:18 +08:00
    @gaobing @luckyrayyy 多谢两位前辈,原来是生产者消费者唤醒问题这么基础大学就学过的案例,回头要再去复习一下恐龙书。
    crella
        13
    crella  
       2020-04-17 01:47:19 +08:00 via Android
    不如定义一个 Deque 类,它的实例变量 data 和 waitlist 是两个数组,类有 add()和 out_call()方法。

    外部通过 Deque.add(obj)方法来给 deque 队列添加元素,也就是添加到 data 数组里。然后 add()方法快结束时给 waitlist 添加所有在 data 里的对象,然后新建线程执行 out_call()方法。

    out_call()方法执行时,新建数组 currentlist=waitlist 深拷贝,然后逐个对应删除 waitlist 内的对象,然后遍历本函数内的 currentlist 执行外部函数操作即可。

    我不会协程,只会简单的多线程操作。上面涉及到 data 和 waitlist 的注意加好互斥锁。


    其实说简陋点,像 windows 窗口,点击一下按钮就有反应,实际上是 window UI 线程在主循环,而不是外部函数在循环检查 win UI 线程。把 Deque 类当作 win UI 线程应该可以。实际上听说 winform 程序都是把 UI 当做主线程的。再说得简单点就是把 Deque 类当成数组并给它加一个“点击按钮”后的操作,这里的“点击按钮”应该就是多线程往数组添加吧。

    我之前给 ruby 的 Array 也添加一个操作,让它被添加元素后自动执行操作。后来想一下还是用类似上面的 Deque 类包装一个类型为 Array 的实例变量好了。


    以上都未经验证,纯属猜想。
    hsyu53
        14
    hsyu53  
       2020-04-17 01:50:14 +08:00
    c++的话,可以用 mutex + condition variable
    Mithril
        15
    Mithril  
       2020-04-17 02:02:15 +08:00
    直接用 ReactiveX 就好了,响应式的思路明显更简单。
    虽说实际上也是开了线程处理吧。
    45HXlKzal6W56zUJ
        16
    45HXlKzal6W56zUJ  
       2020-04-17 10:47:03 +08:00
    为啥不直接 Queue.get()呢
    默认就是 block 永不超时
    45HXlKzal6W56zUJ
        17
    45HXlKzal6W56zUJ  
       2020-04-17 10:48:06 +08:00
    哦,你这不是 python..
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2501 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 42ms UTC 05:12 PVG 13:12 LAX 22:12 JFK 01:12
    Do have faith in what you're doing.
    ubao msn 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