在长时间运行的过程中是否应该留下空闲线程?

时间:2016-01-05 16:10:53

标签: multithreading go daemon

我正在创建一个go计划,旨在长期运行并倾听工作。当它收到请求时,它会在进程队列上运行工作。

我是Golang和系统编程的新手,所以我的问题是:我应该在程序启动时启动进程队列(使用它的多个空闲工作线程)(他们只会坐在那里直到工作结束in)或者我应该在工作到来时将它们旋转并在完成时将它们关闭?

我不清楚多个空闲线程对整个系统的影响,但我假设它们处于空闲状态,直到工作到来才会产生影响。话虽如此,我想确保我的节目是一个好邻居"并且尽可能高效。

- 编辑 -

澄清,"流程池"是一群等待在频道上工作的工作人员。它们应该在工作到来时启动/停止,还是在程序启动时启动并等待工作进入?

3 个答案:

答案 0 :(得分:1)

首先,您无法使用标准Go库创建线程。在Go Universe中,你应该使用所谓的green threads的goroutine。

通常你不应该产生“可重复使用”的goroutines。它们创造起来很便宜所以当工作岗位到达并完成工作(从goroutine返回)后,按需创建它们。

另外,请不要犹豫,创建嵌套的goroutines。一般来说,如果你觉得你应该以并发的方式做某些事情并且不试图重复使用它们就像疯了一样产生它们,因为它没有任何意义。

答案 1 :(得分:1)

无论哪种方式成本都很低。 goroutines不需要单独的操作系统线程,并且在阻止通道接收时几乎不消耗任何资源,但也很少花费非常旋转,所以没有很好的理由离开他们打开了。

我的代码很少使用工作池。一般来说,我的制作人会为它制作的每一个单位产生一个goroutine,并直接将它与一个响应通道一起交出,然后产生一个"听众"为工作输出做一些格式化并将所有响应传递回主线程。我的常见模式如下:

func Foo(input []interface{}) resp chan interface{} {
    var wg sync.WaitGroup
    resp := make(chan interface{})
    listen := make(chan interface{})
    theWork := makeWork(input)
    // do work
    for _, unitOfWork := range theWork {
        wg.Add(1)
        go func() {
            // doWork has signature:
            //   func doWork(w interface{}, ch chan interface{})
            doWork(unitOfWork, listen)
            wg.Done()
        }()
    }
    // format the output of listen chan and send to resp chan
    // then close resp chan so main can continue
    go func() {
        for r := range listen {
            resp <- doFormatting(r)
        }
        close(resp)
    }()
    // close listen chan after work is done
    go func() {
        wg.Wait()
        close(listen)
    }()
    return resp
}

然后我的main函数传递一些输入并侦听响应通道

func main() {
    loremipsum := []string{"foo", "bar", "spam", "eggs"}
    response := Foo(loremipsum)
    for output := range response {
        fmt.Println(output)
    }
}

答案 2 :(得分:0)

具有任务队列和等待工作者的模式在Go中很常见。 Goroutines很便宜,但执行顺序是不确定的。因此,如果您希望系统行为可预测,您最好通过循环中请求的无缓冲通道或其他方式控制工作人员与主例程会合。否则,其中一些可能会产生,但仍然是合法的。