英文:
How to make a select case non-blocking in for loop without default
问题
我有这段代码。
func Start() bool {
    for {
        if checkSomthingIsTrue() {
            if err := doSomthing(); err != nil {
                continue
            }
        }
        select {
        case <-ctx.Done():
            return true
        }
    }
}
如何使上述函数非阻塞,而不使用default: case。
不使用default case的原因是它会一直占用100%的CPU。
答案:
我使用了time.Ticker来进行节流。
谢谢。
英文:
I have this piece of code.
func Start() bool {
	for {
		if checkSomthingIsTrue() {
			if err := doSomthing(); err != nil {
				continue
			}
		}
		select {
		case <-ctx.Done():
			return true
		}
	}
}
How to make the above function non blocking without using default: case.
reason to not use default case is because its eating up 100% CPU always.
Answer:
I have used time.Ticker to throttle
Thanks
答案1
得分: 6
这里存在一个基本误解。一个线程只能做两件事情:
- 
一个线程可以阻塞,等待某些事情发生。
 - 
一个线程可以运行,使用 CPU。
 
如果一个线程从不阻塞,那么它将使用 100% 的可用 CPU。你无法使非阻塞代码使用少于 100% 的可用 CPU。
你有三个选项:
- 
使用非阻塞代码,并接受 100% 的 CPU 使用率。
 - 
重新设计
checkSomthingIsTrue(),使其使用通道,并可以放在select块中。for { select { case <-ctx.Done(): return true case <-whenSomethingIsTrue(): if err := doSomthing(); err != nil { continue } } } - 
使用超时来限制循环,例如:
// 每 100ms 进行一次轮询。 const pollInterval = 100 * time.Millisecond for { select { case <-ctx.Done(): return true case <-time.After(pollInterval): if checkSomthingIsTrue() { if err := doSomthing(); err != nil { continue } } } } 
还要注意,continue 没有意义,但这是另一个问题。
英文:
There is a fundamental misunderstanding here. A thread can do only two things:
- 
A thread can block, waiting for something.
 - 
A thread can run, using CPU.
 
If a thread never blocks, then it uses 100% of the available CPU. You cannot make non-blocking code use less than 100% of the available CPU.
You have three options:
- 
Use non-blocking code, and accept the 100% CPU usage.
 - 
Redesign
checkSomthingIsTrue()so it uses a channel, and can be put inside theselectblock.for { select { case <-ctx.Done(): return true case <-whenSomethingIsTrue(): if err := doSomthing(); err != nil { continue } } } - 
Use a timeout to throttle the loop, for example:
// Poll every 100ms. const pollInterval = 100 * time.Millisecond for { select { case <-ctx.Done(): return true case <-time.After(pollInterval): if checkSomthingIsTrue() { if err := doSomthing(); err != nil { continue } } } } 
Also note that continue makes no sense, but that is a different issue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论