Multithreading 在长时间运行的进程中是否应该保留空闲线程?

Multithreading 在长时间运行的进程中是否应该保留空闲线程?,multithreading,go,daemon,Multithreading,Go,Daemon,我正在创建一个围棋计划,旨在长期运行和倾听工作。当它收到请求时,它在进程队列上运行工作 我不熟悉golang和系统编程,所以我的问题是:我应该在程序启动时启动进程队列(有多个空闲的工作线程)(它们将一直坐在那里直到工作到来),还是应该在工作到达时启动它们,并在完成时关闭它们 我不清楚多个空闲线程对整个系统的影响,但我假设,因为它们是空闲的,所以在工作完成之前不会有任何影响。也就是说,我想确保我的程序是一个“好邻居”,并且尽可能高效 --编辑-- 澄清一下,“进程池”是一组在通道上等待工作的wor

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

我不熟悉golang和系统编程,所以我的问题是:我应该在程序启动时启动进程队列(有多个空闲的工作线程)(它们将一直坐在那里直到工作到来),还是应该在工作到达时启动它们,并在完成时关闭它们

我不清楚多个空闲线程对整个系统的影响,但我假设,因为它们是空闲的,所以在工作完成之前不会有任何影响。也就是说,我想确保我的程序是一个“好邻居”,并且尽可能高效

--编辑--


澄清一下,“进程池”是一组在通道上等待工作的worker go例程。它们应该在工作到达时启动/停止,还是在程序启动时启动并等待工作到来?

首先,您不能使用标准Go库创建线程。在围棋世界中,你应该使用所谓的goroutines

通常你不应该产生“可重用”的goroutine。创建它们的成本很低,所以在工作任务到达时按需创建它们,并在工作完成后立即完成(从goroutine返回)


也不要犹豫创建嵌套的goroutine。一般来说,如果你觉得你应该以并发的方式做一些事情,不要试图重用它们,因为这没有任何意义。

任务队列和等待工作人员的模式在围棋中很常见。goroutine很便宜,但执行顺序是不确定的。所以,如果您希望系统行为是可预测的,您最好通过循环中请求的无缓冲通道或其他方式来控制工作人员与主例程会合。否则,它们中的一些可以繁殖,但仍然闲置,这是合法的。

这两种方法的成本都很低。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
}

在golang中没有“创建线程”这样的概念。如果你说的是goroutines;它们很便宜。根据需要启动它们。goroutines在其函数返回时结束。你通常不会有“闲散”的goroutines坐在那里,他们不是在做什么就是回来了。是的,我为不正确的命名道歉,goroutines就是我所说的。因此,拥有一个长时间运行的“空闲”goroutine池在通道上等待消息是没有问题的?@SjB如何获得一个空闲goroutine池。这听起来不对。Goroutines不需要操作系统线程,并且有一个非常小的堆栈。让一个池等待消息是没有问题的,但是因为生成消息的成本太低,所以“工作线程池”通常不是构建程序的正确方式。谢谢,但我正在寻找一种任务队列模式,其中有可重用的工作线程等待传入的工作。关于绿色线程的链接非常有用!是的,但你也说过“在通道上等待工作”,所以我的建议是编写一个代码,使用通道中的工作任务(这是同步的),并在工作到达时生成一个goroutine,而不是重复使用旧的。谢谢,这就是我想要的模式:工作是完全相同的,不需要按照特定的顺序执行
func main() {
    loremipsum := []string{"foo", "bar", "spam", "eggs"}
    response := Foo(loremipsum)
    for output := range response {
        fmt.Println(output)
    }
}