【问题标题】:How to kill blocking go routine如何杀死阻塞 goroutine
【发布时间】:2016-02-20 01:20:02
【问题描述】:

所以我正在尝试实现一个简单地监听 Redis 订阅的 go 例程(我为此使用 Go-redis 库)然后发送消息 在接收/处理 redis 消息后在通道上。

类似这样的:

func foo(redis *redis.Client, comm chan HandlerSignal) {

    ...

    for {
        msg, err := pubsub.ReceiveMessage()
        sig := HandlerSignal{msg}
        comm <- sig
    }
}

但我想不出告诉 goroutine 在阻塞和等待 redis 消息时返回的最佳方法。

有谁知道这种情况的常见做法,还是我做错了?

【问题讨论】:

  • 是的,为退出/中止添加另一个通道,然后在 for 循环中添加一个选择,并在该通道发出信号时监听返回。
  • 对于其他 Redis 客户端,您可以通过取消订阅所有频道的客户端来告诉订阅者停止阅读。 go-redis 不支持这个。另一种方法是在收到可区分的哨兵消息时中断循环并从应用程序发送该消息。

标签: go goroutine


【解决方案1】:

正如我在这里看到的:https://github.com/go-redis/redis/blob/v3.2.30/pubsub.go#L253pubsub.ReceiveMessage() 在内部使用ReceiveTimeout(5 * time.Second)。为什么不使用相同的功能(如@Tomasz Kłak 建议的那样)?

func foo(redis *redis.Client, comm chan HandlerSignal, quit chan struct{}) {
    ...
    for {

        select {
        case <-quit:
            return
        default:
            msg, err := pubsub.ReceiveTimeout(5 * time.Second)
            sig := HandlerSignal{msg}
            comm <- sig    
        }
    }
}

由于 ReceiveTimeout 会在接下来的 5 秒内阻塞例程,默认情况下不会饱和。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2014-06-27
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    相关资源
    最近更新 更多