2017-06-17 3 views
-3

Ich möchte es parallel laufen basierend auf der Anzahl der Thread. Aber das Ergebnis war nicht so, wie ich es erwartet hatte. Ich weiß nicht, wie ich es effizient und schnell machen kann.Parallelität von Slices

Ich endete mit diesem Code.

package main 

import (
    "fmt" 
    "io/ioutil" 
    "net/http" 
    "os" 
    "runtime" 
    "strconv" 
    "strings" 
    "sync" 
    "time" 
) 

func main() { 
    start := time.Now() 
    target := os.Args[1] 
    thread, _ := strconv.Atoi(os.Args[3]) 
    file, err := ioutil.ReadFile(os.Args[2]) 
    if err != nil { 
     fmt.Println("Error: Please double check if the file " + os.Args[2] + " is exist!") 
     os.Exit(0) 
    } 
    wordlist := strings.Split(string(file), "\n") 

    var wg sync.WaitGroup 
    runtime.GOMAXPROCS(runtime.NumCPU()) 
    jobs := make(chan string) 
    for i := 0; i < thread; i++ { 
     wg.Add(1) 
     defer wg.Done() 
     for _, word := range wordlist { 
      go func(word string) { 
       jobs <- word 
      }(word) 
     } 
    } 

    go func() { 
     for job := range jobs { 
      code := visit(target + job) 
      fmt.Println(target + job + " - " + strconv.Itoa(code)) 
     } 
    }() 
    wg.Wait() 

    elapsed := time.Since(start) 
    fmt.Printf("Timer: %s\n", elapsed) 
} 

func visit(url string) int { 
    data, err := http.Get(url) 
    if err != nil { 
     panic(err) 
    } 
    return data.StatusCode 
} 

Jede Hilfe wäre willkommen. Vielen Dank.

aktualisiert Dies ist meine aktuellen Ergebnisse:

$ go run test.go http://localhost/ word.txt 2 
http://localhost/1 - 404 
http://localhost/1 - 404 
http://localhost/7 - 404 
http://localhost/8 - 404 
http://localhost/9 - 404 
http://localhost/0 - 404 
http://localhost/ - 200 
http://localhost/3 - 404 
http://localhost/2 - 404 
http://localhost/4 - 404 
http://localhost/6 - 404 
http://localhost/2 - 404 
http://localhost/3 - 404 
http://localhost/4 - 404 
http://localhost/5 - 404 
http://localhost/9 - 404 
http://localhost/7 - 404 
http://localhost/8 - 404 
http://localhost/0 - 404 
http://localhost/5 - 404 
http://localhost/ - 200 
http://localhost/6 - 404 
+1

Bitte führen Sie die Fehler, Sie werden immer zusammen mit dem a [minimal, vollständig nachprüfbar Beispiel] (https://stackoverflow.com/help/how-to-ask) Ihr Problem zu erklären. – abhink

+0

Sie können den gepufferten Kanal 'jobs: = make (chan string, 100)' anstelle des blockierten Kanals 'jobs: = make (chan string)' verwenden. Aktualisieren Sie auch den 'defer' für waitgroup wie von @abhink erwähnt. – jeevatkm

+0

@abhink oh ok, sorry. Ich werde meine Frage aktualisieren. – Alkha

Antwort

1

Du richtig waitgroup nicht verwenden. Die defer 's in main' s for-Schleife werden nie aufgerufen, da main nie zurückkehrt und als Ergebnis wg.Wait() Anruf nie entsperrt.

Put defer Anrufe in der goroutine die Nachricht zu senden:

// ... 
for i := 0; i < thread; i++ { 
    wg.Add(1) 

    for _, word := range wordlist { 
     go func(word string) { 
      defer wg.Done() 
      jobs <- word 
     }(word) 
    } 
} 
// ... 

Auch schließen die jobs Kanal:

// ... 
wg.Wait() 
close(jobs) 
// ... 
+0

Hallo @abhink, ich habe versucht, es auf meinen Code zu setzen, aber ich habe ein anderes Problem. Der Prozess wurde nach dem X-Thread gestoppt. $ gehen test.go http laufen: // localhost/word.txt 10 http: // localhost/2-404 http: // localhost/7-404 http: // localhost/3-404 http : // localhost/4 - 404 http: // localhost/5 - 404 http: // localhost/6 - 404 http: // localhost/- 200 http: // localhost/8 - 404 http: // localhost/9 - 404 Timer: 3.734229ms – Alkha

+0

Versuchen Sie, den Job-Kanal zu schließen. – abhink

0

Sie neue goroutine pro neuen Arbeitsplatz schaffen sollte, nicht pro neuen Job hinzugefügt

Hier erstellen Sie ein Logbuch von Goroutinen, um nur 1 Wort zu channeln. Dies ist ein Overkill für solch eine einfache Operation.

Aber Job mit dem Abrufen von URL ist schwerer, aber starten Sie nur 1 Goroutine dafür.

go func() { 
    for job := range jobs { 
     code := visit(target + job) 
     fmt.Println(target + job + " - " + strconv.Itoa(code)) 
    } 
}() 

Wie @abhink erwähnt hat man nicht WaitGroup funktioniert nicht richtig. Tun Sie wg.Add(1) vor dem Erstellen jeder Goroutine und tun Sie wg.Done() am Ende jeder Goroutine. Und natürlich wg.Wait() warten alle laufenden goroutines zu beenden. Beispiel:

var wg sync.WaitGroup 

wg.Add(1) 
go func(param){ 
    defer wg.Done() 
    //... 
}(url) 

//... 

wg.Wait()