2013-12-23 5 views
1

Я хочу создать производителя/потребителя с программой-менеджером в Go. Например: у меня есть 5 producers, 5 consumers and manager. Производители имеют their own local arrays, они перебирают их и отправляют элементы менеджеру. Потребители имеют their own local arrays с информацией, которую потребляют элементы; они посылают их менеджеру тоже. У менеджера есть own array, где хранится то, что и сколько элементов есть (например, если производитель отправляет 1 1 2 3 1 2 0 элементов, массив диспетчера выглядит как 1 3 2 1 (один 0, три 1, два 2 и один 3) и обрабатывает производителей 'и запросы потребителей - поместить элемент в массив (произвести) или удалить его (потреблять).Concurrent Producer and Consumer in Go

Возможно ли сделать такую ​​программу в Go? Я уже сделал это в JAVA + CSP с каналами для отправки info и guard в менеджере, чтобы определить, какая процедура должна выполняться сначала, когда производитель и потребитель пытаются обработать один и тот же элемент (например, производитель хочет добавить 1 в массив менеджера и в то же время потребитель хочет потреблять 1) .

Любые exa спеты или советы приветствуются, потому что я не нахожу информацию о том, что я хочу делать. При необходимости я могу предоставить код JAVA + CSP.

ОБНОВЛЕНИЕ. Как насчет синхронизации (не брать из пустого массива)? Например, если потребитель хочет потреблять элемент из массива диспетчера, который еще не существует (например, потребитель хочет потреблять «3», но у менеджера нет ни одного из них), но у производителя есть этот элемент, и он будет выпущен после нескольких итерации - как я могу заставить потребителей проверять массив менеджеров снова и снова до тех пор, пока работа производителей не будет завершена? Должен ли я создавать структуры (или классы) для элементов потребителей и отмечать, что они используются или нет, или Go имеет конкретные методы для этого?

ответ

2

Вот полный пример, включая очистку канала. После того, как все потребители и продюсеры закончены, Менеджер распечатывает результат (для которого я использовал карту, а не фрагмент, так как я думаю, что это делает код еще проще).

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) 
} 
+0

Просто нужно изменить эту строку 'for i: = range ns' to 'for _, i: = range ns' и все работает так, как ожидалось, спасибо. Но теперь у меня другая проблема, я обновил свой вопрос, если вы можете взглянуть. – Eddwhis

2

я сделал очень похожий пример тому, что вы пытаетесь сделать, это проверить суть github gist

Путь я реализовывал который использует один канал для моего процесса потребителя, а другой для моих 2х процессов, которые производят предметы , блок for контролирует толчок от производителей к потребителю и всякий раз, когда производители arent толкают что-либо, цикл будет default. Объекты, перемещаемые по каналам, представляют собой срезы, процессы будут создавать и потреблять заголовки в каждом сегменте, отправленном по каналу. Я считаю, что вы можете настроить этот код в соответствии с вашим примером.

+0

Спасибо за ответ и пример, я попробую! – Eddwhis

+0

Удачи сэр, и не стесняйтесь комментировать здесь, если вам нужна дополнительная помощь. – ymg

Смежные вопросы