2017-10-14 32 views
0

所以我有这样一个文件:读取文件最佳的方式同时在围棋

NAME : a280 
COMMENT : drilling problem (Ludwig) 
TYPE : TSP 
DIMENSION: 280 
EDGE_WEIGHT_TYPE : EUC_2D 
NODE_COORD_SECTION 
    1 288 149 
    2 288 129 
    3 270 133 
    4 256 141 
    5 256 157 
    6 246 157 
    7 236 169 
    8 228 169 
    9 228 161 
10 220 169 
11 212 169 
12 204 169 
13 196 169 
14 188 169 
15 196 161 

等等...

的数字是城市解决TSP的绳索。我正在尝试在Golang中写这个。现在这个例子可以像200个城市,甚至40,000个城市。我想获得最好的解决方案,所以我想我应该同时处理这个文件。我有下面的代码:

package main 

import (
    "bufio" 
    "fmt" 
    "os" 
    "regexp" 
    "strings" 
) 

func getCords(queue chan string) { 
    cords := regexp.MustCompile(`\s*\d+\s+\d+\s+\d+`) 
    for line := range queue { 
     if cords.MatchString(line) { 
      fmt.Println(line) 
     } 
    } 
} 

func readFile(fileName string) { 
    cords := make(chan string) 
    file := strings.NewReader(fileName) 
    go func() { 
     scanner := bufio.NewScanner(file) 
     for scanner.Scan() { 
      cords <- scanner.Text() 
     } 
     close(cords) 
    }() 
} 

// Menu - main program menu 
func Menu() { 
    reader := bufio.NewReader(os.Stdin) 
    fmt.Println("================== Projektowanie efektywnych algorytmów ==================") 
    fmt.Println("================== Zadanie nr 1 - Algorytm xyz    ==================") 
    // Wczytywanie pliku z danymi 
    // Format: Lp. X Y 
    fmt.Printf("\nPodaj nazwę pliku: ") 
    fileName, err := reader.ReadString('\n') 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    readFile(fileName) 
} 

func main() { 
    Menu() 
} 

在功能getCords我需要useregex辩论,因为这些文件往往有在开始信息的一部分。

问题始于readFile()。我启动了一个goroutine,它可以逐行扫描文件,并获取所有通道的信息。当然执行只是启动它,并进一步。现在的问题是,在拨打go func()之后,我将不得不尝试从频道中读取。该解决方案我发现SO,并在互联网上分别如下:

func readFile(fileName string) { 
    cords := make(chan string) 
    file := strings.NewReader(fileName) 
    go func() { 
     scanner := bufio.NewScanner(file) 
     for scanner.Scan() { 
      cords <- scanner.Text() 
     } 
     close(cords) 
    }() 
    for i := 0; i < 100; i++ { 
     go getCords(cords) 
    } 
} 

所以TE getCords的第一次执行可能会甚至什么都不做,因为够程不会弄到行至通道快。接下来的迭代可能会完成这项工作,但问题是我必须编写一些数字,如本例中的100,并且它可能太高,所以频道将像10次迭代一样关闭,之后它只是浪费时间或者它可能太低,然后我不会得到所有的结果。

你如何解决这样的问题,伙计们?有没有最佳的方式,或者我必须坚持一些waitGroups

+0

首先编写一个工作的顺序版本,然后使用分析找出程序最慢的部分,最后开始在相关位置添加并发程序。此外,https://github.com/AkshanshChahal/TSP-Golang –

+0

您不在代码中的任何位置打开任何文件。 'file:= strings.NewReader(fileName)'不会打开并从'fileName'加载数据。 'os.Open'是这样做的:https://golang.org/pkg/os/#Open。 – abhink

回答

1

我认为是的,最好使用sync.WaitGroup来确保所有的goroutines都完成了他们的工作。一个可能的解决方案:

func getCords(queue Chas string, wg sync.WaitGroup) { 
    defer wg.Done() 
    // your code 
} 

func readFile(fileName string) { 
    cords := make(chan string) 
    file := strings.NewReader(fileName) 

    go func() { 
     scanner := bufio.NewScanner(file) 
     for scanner.Scan() { 
      cords <- scanner.Text() 
     } 
     close(cords) 
    }() 

    wg := sync.WaitGroup{} 
    for i := 0; i < 100; i++ { 
     wg.Add(1) 
     go getCords(cords, wg) 
    } 
    wg.Wait() 
} 
+0

但是一个goroutine完成了对该频道的所有阅读。所以这个例程开始了,执行进一步。然后,我应该在哪里调用'go getCords()' – Frynio

+0

我已经更新了代码。这不是问题 - 因为写入'cords < - scanner.Text()'将被阻止。因为在getCoords'例程启动之前没有人阅读该频道。您也可以交换这两个区块:在开始生产者 - 文件读取器之前启动消费者'getCoords'。 –

+0

对,忘记发送块goroutine,直到有人从频道读取。我不必通过指针传递'wg'吗?你为什么要为'100'迭代做for循环,当我们不知道它会读取多少行? – Frynio

相关问题