【问题标题】:Asynchronous queues with serial data for several channels具有多个通道的串行数据的异步队列
【发布时间】:2017-10-01 13:57:46
【问题描述】:

有一个问题...我有三个实现一个接口的结构。我有一个处理结构数据的函数,但碰巧处理某些结构的数据可能需要几秒钟。数据必须按顺序处理。

我是这样做的:

type dater struct {
    value int
}

type waiter struct {
    data chan *dater
}

func (dat *waiter) conf(wait bool) {
    go func() {
        for {
            obj := <-dat.data
            if wait {
                time.Sleep(5 * time.Second)
            }
            fmt.Println("WAIT", wait, *obj)
        }
    }()
}

func (dat *waiter) gowrite(w *dater) {
    dat.data <- w
}

func main() {
    waiters := []*waiter{}

    first := &waiter{data: make(chan *dater)}
    first.conf(false)
    waiters = append(waiters, first)

    second := &waiter{data: make(chan *dater)}
    second.conf(true)
    waiters = append(waiters, second)

    for i := 0; i < 30; i++ {
        for _, wait := range waiters {
            wait.gowrite(&dater{value: i})
        }
    }
}

输出:

WAIT false {0}
WAIT false {1}
WAIT true {0} (SLEEP 5 sec)
WAIT false {2} (will appear after 5 seconds)
WAIT true {1}
WAIT false {3}
WAIT true {2}
WAIT false {4}
WAIT true {3}
WAIT false {5}

我想要:

WAIT false {0}
WAIT false {1}
WAIT false {2}
WAIT false {3}
WAIT false {4}
WAIT false {5}
WAIT true {0} (5 seconds have passed and we show the first message)
WAIT true {1} (This message will appear after 5 seconds)
WAIT true {2}
WAIT true {3}

“second”结构的“gowrite”函数一直等待,直到结构“first”的通道接收到数据。但对我来说重要的是它们异步处理数据而不会相互阻塞。在这种情况下,所有通道都会收到正确的数据。

【问题讨论】:

  • 我不是狂热的 Go 程序员,但您似乎正在编写反模式代码。
  • @Rafael 它没有帮助:)
  • 查看pipeline 模型。您几乎应该从不在 go 例程中调用 sleep。

标签: go


【解决方案1】:

看来您需要两个单独的缓冲通道,like so

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    wg.Add(2)
    go first()
    go second()
    for i := 1; i < 10; i++ {
        a <- i // send to first
        b <- i // send to second
    }
    close(a)
    close(b)
    wg.Wait()
}

func first() {
    for {
        d, ok := <-a
        time.Sleep(100 * time.Millisecond)
        if !ok {
            break
        }
        fmt.Println("first job:", d) // do first job here.
    }
    wg.Done()
}

func second() {
    for {
        d, ok := <-b
        time.Sleep(300 * time.Millisecond)
        if !ok {
            break
        }
        fmt.Println("second job:", d) // do second job here.
    }
    wg.Done()
}

var a = make(chan int, 1000)
var b = make(chan int, 1000)
var wg sync.WaitGroup

输出:

first job: 1
first job: 2
second job: 1
first job: 3
first job: 4
first job: 5
second job: 2
first job: 6
first job: 7
first job: 8
second job: 3
first job: 9
second job: 4
second job: 5
second job: 6
second job: 7
second job: 8
second job: 9

【讨论】:

  • 感谢您的回答。如果我在 "fmt.Println (" second job: ", d)" 之后添加 "sleep" time.Sleep (100 * time.Second) 那么我得到:第一份工作:1,第一份工作:3(?),第二份工作:2。我想看看:第一份工作:1,第一份工作:3,第二份工作2,第一份工作5,第一份工作7等。你的例子和我的问题一样。
  • 我需要两个结构中的数据相同。第一个是 1,2,3,4,第二个是 1,2,3,4。用一个长的秒处理,使得前者仍然接收数据,当秒处理一个长的过程时,它继续执行进一步。第一:1,2,3,4,5。第二:1,2(睡眠),3,4,5。感谢您的帮助!
  • 在循环中评论了条件,它似乎很好。但是...我在数组中的数据位置循环了多达 100 个,并且我再次锁定了第一个通道。
  • 使用缓冲通道。你需要详细说明,你的问题不清楚。编辑您的问题添加示例和输出。
  • 对于您提供的数据,我无能为力,看来您需要一些算法来解决您的问题,为了在 Stackoverflow 中获得更好的帮助,最好尽可能简单地问每个线程一个问题。并为每个问题提供您的示例输入和输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 2013-09-06
  • 2021-10-24
  • 1970-01-01
  • 2019-02-09
  • 2017-05-16
相关资源
最近更新 更多