- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我刚刚在 Mac 上安装了 Go,这是代码
package main
import (
"fmt"
"time"
)
func Product(ch chan<- int) {
for i := 0; i < 100; i++ {
fmt.Println("Product:", i)
ch <- i
}
}
func Consumer(ch <-chan int) {
for i := 0; i < 100; i++ {
a := <-ch
fmt.Println("Consmuer:", a)
}
}
func main() {
ch := make(chan int, 1)
go Product(ch)
go Consumer(ch)
time.Sleep(500)
}
我“去运行 producer_consumer.go”,屏幕上没有输出,然后退出。
我的程序有问题吗?如何解决?
最佳答案
这是一个相当冗长的答案,但简单地说:
time.Sleep
等待直到希望其他例程完成他们的工作是不好的。 在这个相当冗长的答案的底部,我试图解释一些基本概念和最佳实践(好吧,更好的实践),您会发现您的代码被重写以和显示所有值不依赖time.Sleep
。我没有测试该代码,但应该没问题
是的,这里有几个问题。正如项目符号列表:
鉴于您已经知道要将多少值推送到 channel ,为什么不简单地创建 ch := make(chan int, 100)
?这样,您的发布者就可以继续将消息推送到 channel ,而不管消费者做什么。
您不需要这样做,但是根据您要执行的操作向您的 channel 添加一个合理的缓冲区绝对值得一试。不过目前,这两个例程都在使用 fmt.Println
& co,无论哪种方式都将成为瓶颈。打印到 STDOUT 是线程安全的,并且是缓冲的。这意味着每次调用 fmt.Print*
都会获取一个锁,以避免合并来自两个例程的文本。
您可以简单地将所有值推送到您的 channel ,然后关闭它。然而,这是一种糟糕的形式。 WRT channel 的经验法则是 channel 是在同一个例程中创建和关闭的。意思是:您正在主例程中创建 channel ,这是它应该关闭的地方。
您需要一种同步机制,或者至少密切关注您的例程是否已完成其工作。这是使用 sync
包或通过第二个 channel 完成的。
// using a done channel
func produce(ch chan<- int) <-chan struct{} {
done := make(chan struct{})
go func() {
for i := 0; i < 100; i++ {
ch <- i
}
// all values have been published
// close done channel
close(done)
}()
return done
}
func main() {
ch := make(chan int, 1)
done := produce(ch)
go consume(ch)
<-done // if producer has done its thing
close(ch) // we can close the channel
}
func consume(ch <-chan int) {
// we can now simply loop over the channel until it's closed
for i := range ch {
fmt.Printf("Consumed %d\n", i)
}
}
好的,但是在这里您仍然需要等待 consume
例程完成。
您可能已经注意到 done
channel 在技术上并没有在创建它的同一个例程中关闭。但是,因为例程被定义为闭包,所以这是一个可以接受的折衷方案。现在让我们看看如何使用 WaitGroup :
import (
"fmt"
"sync"
)
func product(wg *sync.WaitGroup, ch chan<- int) {
defer wg.Done() // signal we've done our job
for i := 0; i < 100; i++ {
ch <- i
}
}
func main() {
ch := make(chan int, 1)
wg := sync.WaitGroup{}
wg.Add(1) // I'm adding a routine to the channel
go produce(&wg, ch)
wg.Wait() // will return once `produce` has finished
close(ch)
}
好的,所以这看起来很有希望,我可以让例程在完成任务时告诉我。但是,如果我将消费者和生产者都添加到 WaitGroup ,我就不能简单地遍历 channel 。只有当两个例程都调用 wg.Done()
时, channel 才会关闭,但如果消费者卡在一个永远不会关闭的 channel 上循环,那么我就创建了一个死锁。
此时混合将是最简单的解决方案:将消费者添加到 WaitGroup ,并使用生产者中的完成 channel 来获取:
func produce(ch chan<- int) <-chan struct{} {
done := make(chan struct{})
go func() {
for i := 0; i < 100; i++ {
ch <- i
}
close(done)
}()
return done
}
func consume(wg *sync.WaitGroup, ch <-chan int) {
defer wg.Done()
for i := range ch {
fmt.Printf("Consumer: %d\n", i)
}
}
func main() {
ch := make(chan int, 1)
wg := sync.WaitGroup{}
done := produce(ch)
wg.Add(1)
go consume(&wg, ch)
<- done // produce done
close(ch)
wg.Wait()
// consumer done
fmt.Println("All done, exit")
}
关于Go channel 不适用于生产者/消费者样本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54380193/
我在我的 Xcode 项目目录中输入了以下内容: keytool -genkey -v -keystore release.keystore -alias mykey -keyalg RSA \
假设我有一个像这样的 DataFrame(或 Series): Value 0 0.5 1 0.8 2 -0.2 3 None 4 None 5 None
我正在对一个 Pandas 系列进行相对繁重的应用。有什么方法可以返回一些打印反馈,说明每次调用函数时在函数内部进行打印还有多远? 最佳答案 您可以使用跟踪器包装您的函数。以下两个示例,一个基于完成的
我有一个 DataFrame,其中一列包含列表作为单元格内容,如下所示: import pandas as pd df = pd.DataFrame({ 'col_lists': [[1, 2
我想使用 Pandas df.apply 但仅限于某些行 作为一个例子,我想做这样的事情,但我的实际问题有点复杂: import pandas as pd import math z = pd.Dat
我有以下 Pandas 数据框 id dist ds 0 0 0 0 5 1 0 0 7 2 0 0
这发生在我尝试使用 Gradle 构建时。由于字符串是对象,因此似乎没有理由发生此错误: No signature of method: java.util.HashMap.getOrDefault(
您好,有人可以解释为什么在 remaining() 函数中的 Backbone 示例应用程序 ( http://backbonejs.org/examples/todos/index.html ) 中
我有两个域类:用户 class User { String username String password String email Date dateCreated
问题陈述: 一个 pandas dataframe 列系列,same_group 需要根据两个现有列 row 和 col 的值从 bool 值创建。如果两个值在字典 memberships 中具有相似
apporable 报告以下错误: error: unknown type name 'MKMapItem'; did you mean 'MKMapView'? MKMapItem* destina
我有一个带有地址列的大型 DataFrame: data addr 0 0.617964 IN,Krishnagiri,635115 1 0.635428 IN,Chennai
我有一个列表list,里面有这样的项目 ElementA: Number=1, Version=1 ElementB: Number=1, Version=2 ElementC: Number=1,
我正在编译我的源代码,它只是在没有运行应用程序的情况下终止。这是我得到的日志: Build/android-armeabi-debug/com.app4u.portaldorugby/PortalDo
我正在尝试根据另一个单元格的值更改单元格值(颜色“红色”或“绿色”)。我运行以下命令: df.loc[0, 'Colour'] = df.loc[0, 'Count'].apply(lambda x:
我想弄清楚如何使用 StateT结合两个 State基于对我的 Scalaz state monad examples 的评论的状态转换器回答。 看来我已经很接近了,但是在尝试申请 sequence
如果我已经为它绑定(bind)了集合,我该如何添加 RibbonLibrary 默认的快速访问项容器。当我从 UI 添加快速访问工具项时,它会抛出 Operation is not valid whi
在我学习期间Typoclassopedia我遇到了这个证明,但我不确定我的证明是否正确。问题是: One might imagine a variant of the interchange law
我是一名优秀的程序员,十分优秀!