背景:我正在尝试实现一个逻辑,该逻辑找到可以被1到20之间的所有数字整除的最小正数。我已经实现了一个顺序版本并获得了答案232792560。
问题:当我尝试在此问题上构建一些并发(请参阅未注释的代码块)时,它确实运行但从未显示任何结果。你们中的任何人都可以指导我出错的地方吗?
注意:我非常喜欢golang;而且我知道,这不是并发的最佳问题,因为不能保证我将得到最小的正数作为第一个结果。但是,我出于好奇而尝试了它。
package main
import(
"fmt"
)
func divide(num int) bool {
for i := 1; i <= 20; i++ {
if num % i != 0 {
return false
}
}
return true
}
func main() {
num:=0
//simple function
/*for {
num++;
result := divide(num)
if result {
fmt.Println("Smallest number is: ", num)
break
}
}*/
//go-routine
//go-routine
var wg sync.WaitGroup
for {
num++;
wg.Add(1)
go func(x int) {
result := divide(x)
if result {
fmt.Println("Smallest number is: ", x)
defer wg.Done()
}
}(num)
}
wg.Wait()
fmt.Println("End.")
}
答案 0 :(得分:1)
启动无限数量的goroutine是没有意义的 - 它将比非并发解决方案表现更差。您可以尝试使用&#34;工作池&#34;模式并批量计算。
package main
import (
"fmt"
"runtime"
)
func divide(num int) bool {
for i := 1; i <= 20; i++ {
if num%i != 0 {
return false
}
}
return true
}
const step = 100000
func main() {
result := make(chan int)
jobs := make(chan int)
for w := 0; w < runtime.NumCPU(); w++ {
go func() {
for n := range jobs {
for i := n; i < n+step; i++ {
if divide(i) {
result <- i
}
}
}
}()
}
num := 1
for {
select {
case jobs <- num:
num += step
case x := <-result:
fmt.Println("Smallest number is:", x)
return
}
}
}
答案 1 :(得分:1)
解决问题的另一种方法是过滤器。我们的想法是将一堆goroutine与频道链接起来,并使它们过滤掉所有不通过某些测试的值。在您的情况下,您想要过滤不能被某个数字整除的数字。这是它的外观:
package main
import (
"fmt"
)
func main() {
in := make(chan int)
tmp := in
// Create filter-goroutines
for i := 1; i <= 20; i++ {
tmp = makeDivisor(i, tmp)
}
running := true
// Now feed in all the numbers...
for i := 1; running; i++ {
select {
// Check if a number passed all filters.
case k := <-tmp:
fmt.Printf("Answer is %d\n", k)
close(in)
running = false
// Otherwise feed in the next.
case in <- i:
}
}
}
func makeDivisor(n int, c chan int) chan int {
cc := make(chan int)
go func() {
for i := range c {
if i%n == 0 {
cc <- i
}
}
close(cc)
}()
return cc
}
这是playground。 (请注意,游乐场不会使用20个过滤器,但也可以在本地尝试。)
请注意,第一个过滤器要比进一步进入链中的过滤器做更多的工作。您可以启动更多的第一个过滤器来解决这个问题,尽管整数除法非常快,而且整个事情可能会受到当前频道通信的限制。
有效吗?
答案是232792560
是