下面是Stuff类型的结构。它具有三个整数。A
Number
,它Double
和它的Power
。让我们假设计算给定int列表的double和power是昂贵的计算。
type Stuff struct {
Number int
Double int
Power int
}
func main() {
nums := []int{2, 3, 4} // given numbers
stuff := []Stuff{} // struct of stuff with transformed ints
double := make(chan int)
power := make(chan int)
for _, i := range nums {
go doubleNumber(i, double)
go powerNumber(i, power)
}
// How do I get the values back in the right order?
fmt.Println(stuff)
}
func doubleNumber(i int, c chan int) {
c <- i + i
}
func powerNumber(i int, c chan int) {
c <- i * i
}
的结果fmt.Println(stuff)
应与初始化内容相同,例如:
stuff := []Stuff{
{Number: 2, Double: 4, Power: 4}
{Number: 3, Double: 6, Power: 9}
{Number: 4, Double: 8, Power: 16}
}
我知道我可以使用<- double
并<- power
从通道中收集值,但是我不知道什么双/次方属于什么数字。
Goroutines独立地并行运行,因此,如果没有显式同步,您将无法预测执行和完成顺序。因此,您无法将返回的数字与输入的数字配对。
您可以返回更多数据(例如,输入数字和输出,例如包装在结构中),也可以将指针传递到辅助函数(作为新的goroutine发布),例如*Stuff
,让goroutine自己填充计算出的数据Stuff
。
我将使用的信道类型chan Pair
,其中Pair
是:
type Pair struct{ Number, Result int }
因此计算将如下所示:
func doubleNumber(i int, c chan Pair) { c <- Pair{i, i + i} }
func powerNumber(i int, c chan Pair) { c <- Pair{i, i * i} }
我将使用a,map[int]*Stuff
因为可收集的数据来自多个渠道(double
和power
),并且我想Stuff
轻松快捷地找到合适的数据(需要指针,因此我也可以在“地图”中对其进行修改)。
所以主要功能:
nums := []int{2, 3, 4} // given numbers
stuffs := map[int]*Stuff{}
double := make(chan Pair)
power := make(chan Pair)
for _, i := range nums {
go doubleNumber(i, double)
go powerNumber(i, power)
}
// How do I get the values back in the right order?
for i := 0; i < len(nums)*2; i++ {
getStuff := func(number int) *Stuff {
s := stuffs[number]
if s == nil {
s = &Stuff{Number: number}
stuffs[number] = s
}
return s
}
select {
case p := <-double:
getStuff(p.Number).Double = p.Result
case p := <-power:
getStuff(p.Number).Power = p.Result
}
}
for _, v := range nums {
fmt.Printf("%+v\n", stuffs[v])
}
输出(在Go Playground上尝试):
&{Number:2 Double:4 Power:4}
&{Number:3 Double:6 Power:9}
&{Number:4 Double:8 Power:16}
从现在开始我们传递*Stuff
值,我们可以在Stuff
自身中“预填充”输入数字。
但是必须小心,您只能在正确同步的情况下读取/写入值。最简单的方法是等待所有“工人” goroutine完成工作。
var wg = &sync.WaitGroup{}
func main() {
nums := []int{2, 3, 4} // given numbers
stuffs := make([]Stuff, len(nums))
for i, n := range nums {
stuffs[i].Number = n
wg.Add(2)
go doubleNumber(&stuffs[i])
go powerNumber(&stuffs[i])
}
wg.Wait()
fmt.Printf("%+v", stuffs)
}
func doubleNumber(s *Stuff) {
defer wg.Done()
s.Double = s.Number + s.Number
}
func powerNumber(s *Stuff) {
defer wg.Done()
s.Power = s.Number * s.Number
}
输出(在Go Playground上尝试):
[{Number:2 Double:4 Power:4} {Number:3 Double:6 Power:9} {Number:4 Double:8 Power:16}]
问题内容: 上面的代码创建了100个goroutine,将num插入到通道c,所以我只是想知道,这些goroutine是否会以随机顺序执行?在我的测试期间,输出将始终为1到100 问题答案: 严格来说,您观察到的“随机”行为是不确定性行为。 要了解此处发生的情况,请考虑通道的行为。在这种情况下,它有许多goroutine试图写入通道,而只有一个goroutine从通道中读出。 阅读过程只是顺序的,
通常,您可以有多个进程,但有时在某些操作中,我们需要确保在执行前一个进程之后执行一个进程。 我们如何在卡蒙达实现它?试图找到类似进程依赖关系的东西(因此进程在上一个进程完成后才开始),但找不到任何东西:( 我考虑在process中添加一些变量(比如),并检查指定的process是否已经完成,但也许会有更好的解决方案。
我使用maven failsafe插件触发testng套件,其配置与 但是套件或其中的测试没有按照正确的顺序执行。有没有办法规定套房应按以下顺序执行 某个套房。xml 另一套。xml 还有一套。xml 我不关心套件中测试的执行顺序,但只希望在前一个套件完成后执行一个套件。是否有一些配置可用于实现相同的功能?
如何按特定顺序运行quarkus测试?通常我们有@InSequence注释(来自arquillian IIRC),我们可以实现这一点。 但是我没有找到任何类似的Quarkus在"org.junit.jupiter.api"软件包提供Quarkus-朱尼5。 它将以一个替代的顺序运行,我试图使用org.junit.jupiter.api.顺序与@Testmetodorder(方法命令。nnotati
问题内容: 我有一个XML编写脚本,可以为特定的第三方工具输出XML。 我已经使用原始XML作为模板来确保构建所有正确的元素,但是最终的XML看起来并不像原始XML。 我以相同的顺序编写属性,但是lxml以自己的顺序编写属性。 我不确定,但是我怀疑第3部分工具希望属性按特定顺序显示,并且我想解决此问题,以便查看其属性顺序是否导致失败,或其他原因。 源元素: 我的源脚本: 我生成的XML: 有没有办
问题内容: 我有三个连接的线程,即第二个线程在第一个死后执行。 这是我的代码: 我将如何使用而不是三个线程对象来实现此功能? 问题答案: 如果您想要/需要的是一个接一个地执行一组作业,但要在与主应用程序线程不同的单个线程中执行,请使用。