Concurrency Go中的并发生产者和消费者

Concurrency Go中的并发生产者和消费者,concurrency,go,producer,Concurrency,Go,Producer,我想在Go中创建一个具有manager程序的生产者/消费者。例如:我有一个5个生产者、5个消费者和经理。生产者拥有自己的本地数组,他们迭代这些数组并将元素发送给管理器。消费者拥有他们自己的本地数组,其中包含元素消费的信息;他们也把它们寄给经理。管理者拥有自己的数组,在那里它存储了哪些元素以及有多少个元素(例如,如果制作者发送123120元素,管理者数组看起来像12321(一个0,三个1,两个2和一个3),它处理制作者和消费者的请求-将一个元素放入数组(product)或者移除它(消耗) 有可能在

我想在Go中创建一个具有manager程序的生产者/消费者。例如:我有一个
5个生产者、5个消费者和经理
。生产者拥有自己的本地数组,他们迭代这些数组并将元素发送给管理器。消费者拥有
他们自己的本地数组
,其中包含元素消费的信息;他们也把它们寄给经理。管理者拥有自己的数组,在那里它存储了哪些元素以及有多少个元素(例如,如果制作者发送
123120
元素,管理者数组看起来像
12321
(一个0,三个1,两个2和一个3),它处理制作者和消费者的请求-将一个元素放入数组(product)或者移除它(消耗)

有可能在Go中制作这样的程序吗?我已经在JAVA+CSP中这样做了,通过通道发送信息,并在manager中进行保护,以确定当生产者和消费者尝试处理同一元素时,应该首先执行哪个过程(例如,生产者希望将1添加到管理器阵列,同时消费者希望使用1)

欢迎提供任何示例或建议,因为我找不到任何关于我想做什么的信息。如果需要,我可以提供我的JAVA+CSP代码


更新。同步如何(不要从空数组中获取)?例如,如果使用者希望使用manager数组中尚不存在的元素(例如,使用者希望使用“3”,但manager没有任何元素)但是producer有这个元素,它将在几次迭代后生成-我如何让消费者反复检查manager数组,直到producer的工作完成?我是否需要创建结构(或类)对于消费者元素并标记它们是否被使用,或者Go有具体的方法来执行此操作?

我做了一个与您尝试执行的操作非常类似的示例,请检查此要点


我实现的方法是为我的流程使用者使用一个通道,为产生项目的2x流程使用另一个通道,
for
块控制从生产者到消费者的推送,并且每当生产者不推送任何东西时,循环将
default
esses将生成并使用通过频道发送的每个片段中的标题。我相信您可以调整此代码以适合您的示例。

我做了一个与您尝试做的非常类似的示例,请检查此要点


我实现的方法是为我的流程使用者使用一个通道,为产生项目的2x流程使用另一个通道,
for
块控制从生产者到消费者的推送,并且每当生产者不推送任何东西时,循环将
default
esses将制作和使用通过频道发送的每个片段中的标题。我相信您可以调整此代码以适合您的示例。

下面是一个完整的示例,包括频道清理。在所有消费者和制作人完成后,经理将打印出结果(对于这一点,我使用了一个映射而不是一个切片,因为我认为它使代码更容易一些)

主程序包
输入“fmt”
//Consume以ns为单位处理这些数字,并在完成后在ch上发送它们
//已处理。当例程完成时,它会发出“已完成”的信号。
函数消耗(已完成的循环布尔,循环循环整数,ns[]整数){
对于i:=范围ns{

这里有一个完整的例子,包括频道清理。在所有的消费者和生产者都完成之后,经理会打印出结果(我使用的是地图而不是切片,因为我认为这会使代码更容易一些)

主程序包
输入“fmt”
//Consume以ns为单位处理这些数字,并在完成后在ch上发送它们
//已处理。当例程完成时,它会发出“已完成”的信号。
函数消耗(已完成的循环布尔,循环循环整数,ns[]整数){
对于i:=范围ns{

谢谢你的回答和例子,我会试试的!祝你好运,先生,如果你需要进一步的帮助,请在这里随意评论。谢谢你的回答和例子,我会试试的!祝你好运,先生,如果你需要进一步的帮助,请在这里随意评论。只需要将这行
for I:=range ns
改为
for,I:=range ns
,永远一切正常,谢谢。但是现在我有其他问题,我更新了我的问题,如果你能看一下的话。只需要将这一行
for I:=range ns
更改为
for,I:=range ns
,一切正常,谢谢。但是现在我有其他问题,我更新了我的问题,如果你能看一下的话。
package main

import "fmt"

// Consume processes the numbers in ns, sending them on ch after they're
// processed. When the routine is finished, it signals that on done.
func Consume(done chan bool, ch chan int, ns []int) {
    for i := range ns {
        ch <- i
    }
    done <- true
}

// Produce "creates" the numbers in ns, sending them on ch after they're
// produced. When the routine is finished, it signals that on done.
func Produce(done chan bool, ch chan int, ns []int) {
    for i := range ns {
        ch <- i
    }
    done <- true
}

// Manage creates consumers and producers for the given int slices.
// It returns once all consumers and producers are finished.
func Manage(cons, pros [][]int) {
    cch := make(chan int)
    pch := make(chan int)
    dch := make(chan bool)
    n := len(cons) + len(pros)
    data := make(map[int]int)
    for _, c := range cons {
        go Consume(dch, cch, c)
    }
    for _, p := range pros {
        go Produce(dch, pch, p)
    }
    for n > 0 {
        select {
        case c := <-cch:
            data[c] -= 1
        case c := <-pch:
            data[c] += 1
        case <-dch:
            n -= 1
        }
    }
    close(cch)
    close(pch)
    close(dch)
    fmt.Println(data)
}
func main() {
    cons := [][]int{{1, 3, 5}, {0, 1, 5}}
    pros := [][]int{{0, 1, 1}, {3, 5, 5, 7}}
    Manage(cons, pros)
}