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

2020-04-17 01:00:21 +08:00
 iwdmb

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

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

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

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

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

谢谢大家!

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

1737 次点击
所在节点    问与答
17 条回复
araaaa
2020-04-17 01:21:20 +08:00
用单线程池做定时任务
iwdmb
2020-04-17 01:25:18 +08:00
@araaaa
可能是我描述的不清楚
我主要是想解决在没有延迟的情况处理 deque 中的资料
同时避免 CPU 100% 的问题
iwdmb
2020-04-17 01:26:14 +08:00
sleep 只是其中一个解法,可是我希望可以做到不要延迟的处理 deque
litmxs
2020-04-17 01:28:26 +08:00
入队的时候唤醒线程?
araaaa
2020-04-17 01:29:43 +08:00
@iwdmb #2 调度周期间隔可以定位毫秒或者微秒
luckyrayyy
2020-04-17 01:33:19 +08:00
Java 里面有很多现成的实现,队里为空的时候线程就阻塞了。
iwdmb
2020-04-17 01:34:12 +08:00
@litmxs 與 Golang Channel 的原理其實很相似了。
gaobing
2020-04-17 01:35:31 +08:00
生产者消费者是任何语言的并发或者多线程编程的入门例子吧。。。看你写的像 Java,Java 里面 wait notify 配套,await signal 配套,或者 BlockingQueue 都可以。
iwdmb
2020-04-17 01:35:57 +08:00
@luckyrayyy 看起来思路都是类似的,不知道能不能请前辈推荐 Java 开源项目有類似的實現,感谢。
或是有什么关键字之类的。
iwdmb
2020-04-17 01:37:20 +08:00
@gaobing 看起来就是 BlockingQueue,实在是见识浅薄,真的非常感谢。
luckyrayyy
2020-04-17 01:40:26 +08:00
@iwdmb TransferQueue,LinkedBlockingQuque,ArrayBlockingQueue 。
iwdmb
2020-04-17 01:47:18 +08:00
@gaobing @luckyrayyy 多谢两位前辈,原来是生产者消费者唤醒问题这么基础大学就学过的案例,回头要再去复习一下恐龙书。
crella
2020-04-17 01:47:19 +08:00
不如定义一个 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
2020-04-17 01:50:14 +08:00
c++的话,可以用 mutex + condition variable
Mithril
2020-04-17 02:02:15 +08:00
直接用 ReactiveX 就好了,响应式的思路明显更简单。
虽说实际上也是开了线程处理吧。
dicc
2020-04-17 10:47:03 +08:00
为啥不直接 Queue.get()呢
默认就是 block 永不超时
dicc
2020-04-17 10:48:06 +08:00
哦,你这不是 python..

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/663256

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX