iwdmb
V2EX  ›  问与答

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

  •  
  •   iwdmb · Apr 17, 2020 · 2672 views
    This topic created in 2222 days ago, the information mentioned may be changed or developed.

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

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

    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 replies    2020-04-17 10:48:06 +08:00
    araaaa
        1
    araaaa  
       Apr 17, 2020 via iPhone
    用单线程池做定时任务
    iwdmb
        2
    iwdmb  
    OP
       Apr 17, 2020
    @araaaa
    可能是我描述的不清楚
    我主要是想解决在没有延迟的情况处理 deque 中的资料
    同时避免 CPU 100% 的问题
    iwdmb
        3
    iwdmb  
    OP
       Apr 17, 2020
    sleep 只是其中一个解法,可是我希望可以做到不要延迟的处理 deque
    litmxs
        4
    litmxs  
       Apr 17, 2020 via Android
    入队的时候唤醒线程?
    araaaa
        5
    araaaa  
       Apr 17, 2020 via iPhone
    @iwdmb #2 调度周期间隔可以定位毫秒或者微秒
    luckyrayyy
        6
    luckyrayyy  
       Apr 17, 2020 via iPhone
    Java 里面有很多现成的实现,队里为空的时候线程就阻塞了。
    iwdmb
        7
    iwdmb  
    OP
       Apr 17, 2020
    @litmxs 與 Golang Channel 的原理其實很相似了。
    gaobing
        8
    gaobing  
       Apr 17, 2020 via Android   ❤️ 1
    生产者消费者是任何语言的并发或者多线程编程的入门例子吧。。。看你写的像 Java,Java 里面 wait notify 配套,await signal 配套,或者 BlockingQueue 都可以。
    iwdmb
        9
    iwdmb  
    OP
       Apr 17, 2020
    @luckyrayyy 看起来思路都是类似的,不知道能不能请前辈推荐 Java 开源项目有類似的實現,感谢。
    或是有什么关键字之类的。
    iwdmb
        10
    iwdmb  
    OP
       Apr 17, 2020
    @gaobing 看起来就是 BlockingQueue,实在是见识浅薄,真的非常感谢。
    luckyrayyy
        11
    luckyrayyy  
       Apr 17, 2020 via iPhone   ❤️ 1
    @iwdmb TransferQueue,LinkedBlockingQuque,ArrayBlockingQueue 。
    iwdmb
        12
    iwdmb  
    OP
       Apr 17, 2020
    @gaobing @luckyrayyy 多谢两位前辈,原来是生产者消费者唤醒问题这么基础大学就学过的案例,回头要再去复习一下恐龙书。
    crella
        13
    crella  
       Apr 17, 2020 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  
       Apr 17, 2020
    c++的话,可以用 mutex + condition variable
    Mithril
        15
    Mithril  
       Apr 17, 2020
    直接用 ReactiveX 就好了,响应式的思路明显更简单。
    虽说实际上也是开了线程处理吧。
    45HXlKzal6W56zUJ
        16
    45HXlKzal6W56zUJ  
       Apr 17, 2020
    为啥不直接 Queue.get()呢
    默认就是 block 永不超时
    45HXlKzal6W56zUJ
        17
    45HXlKzal6W56zUJ  
       Apr 17, 2020
    哦,你这不是 python..
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   6174 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 66ms · UTC 02:12 · PVG 10:12 · LAX 19:12 · JFK 22:12
    ♥ Do have faith in what you're doing.