Sie wirklich nicht brauchen jede „CPU-intensive“ Berechnung, man muss nur vermeiden (wie Warten auf Daten über eine Netzwerkverbindung oder das Schreiben in eine Datei) zu blockieren, und Sie müssen mindestens so viele goroutines das tun so viele CPU-Kerne, die Sie haben (dies kann mit runtime.NumCPU()
abgefragt werden). Die Verwendung von ist eine schlechte Idee, da sie möglicherweise auf eine Datei, eine Netzwerkverbindung usw. gerichtet ist und daher das Drucken darauf blockieren kann (E/A-Warte).
Verwenden Sie eine "endlose" Schleife, die nichts tut, außer zu überprüfen, ob es Zeit ist abzubrechen. Sie können dies mit einem einzelnen Kanal tun und ihn schließen, wenn Sie abbrechen möchten (Empfang auf einem geschlossenen Kanal kann sofort fortgesetzt werden, was den Nullwert des Elementtyps des Kanals ergibt), und Goroutines können dies unter Verwendung der select
-Anweisung überprüfen mit einem default
Zweig sonst würde es nur blockieren). Sie müssen nicht einmal die maximale Anzahl an CPUs festlegen, die gleichzeitig ausgeführt werden können (runtime.GOMAXPROCS()
), da dies standardmäßig der Anzahl der verfügbaren Cores seit Go 1.5 entspricht. Einfachste Lösung:
done := make(chan int)
for i := 0; i < runtime.NumCPU(); i++ {
go func() {
for {
select {
case <-done:
return
default:
}
}
}()
}
time.Sleep(time.Second * 10)
close(done)
Dieser Code hat Race Conditions, Zugriffe auf die lokale Variable 'keepGoing' sind nicht synchronisiert (mit der Option '-race' zur Überprüfung). Besser Kanäle für so etwas zu verwenden. – icza
Ich sah nicht die Notwendigkeit, da dieses Programm direkt nach dem Schlaf beendet. In der Tat, jetzt, wo Sie es erwähnen, ist auch die "keepGoing" Variable nicht notwendig, wenn dieses Programm als Ganzes ausgeführt werden soll. – noisypixy
Das ist nicht wahr. So wie es ist, sind Sie in den Händen des Goroutine Scheduler, und wenn die Haupt Goroutine nicht nach dem Schlaf geplant wird, könnte Ihre App laufen "für immer" .. – icza