Cara menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai adalah soalan yang sering ditanya. Dalam Go, menutup saluran ialah cara untuk memberitahu penerima bahawa tiada lagi data. Dengan menutup saluran, penerima boleh mengetahui tepat pada masanya bahawa pengirim telah menyelesaikan semua operasi penghantaran. Dalam saluran yang dipenuhi dengan berbilang goroutin, kita boleh menggunakan kaunter untuk menjejaki berapa banyak lagi goroutin yang menghantar data ke saluran. Apabila kaunter turun kepada 0, semua kerja telah selesai dan kami boleh menutup saluran dengan selamat. Selepas menutup saluran, penerima boleh menentukan sama ada saluran telah ditutup dengan menggunakan pembolehubah tambahan dalam ungkapan terima. Dengan cara ini, kami boleh memastikan saluran yang diisi oleh berbilang goroutin ditutup dengan betul selepas semua kerja selesai, sekali gus mengelakkan kebocoran sumber dan isu kebuntuan.
Saya cuba mengikuti cara Go iaitu "jangan berkomunikasi melalui memori yang dikongsi, tetapi berkongsi memori melalui komunikasi" dan menggunakan saluran untuk menyampaikan tugasan secara tidak segerak untuk diselesaikan dan menghantar semula hasil tugasan pemprosesan.
Untuk memudahkan, saya telah menukar jenis saluran kepada int dan bukannya struktur sebenar mereka. Dan menggantikan pemprosesan lama dengan time.Sleep()
.
Bagaimana untuk menutup ProducedResults
,以便此代码不会卡在最后一个 for
selepas semua keputusan tugasan dihantar semula?
quantityOfTasks:= 100 quantityOfWorkers:= 60 remainingTasks := make(chan int) producedResults := make(chan int) // produce tasks go func() { for i := 0; i < quantityOfTasks; i++ { remainingTasks <- 1 } close(remainingTasks) }() // produce workers for i := 0; i < quantityOfWorkers; i++ { go func() { for taskSize := range remainingTasks { // simulate a long task time.Sleep(time.Second * time.Duration(taskSize)) // return the result of the long task producedResults <- taskSize } }() } // read the results of the tasks and agregate them executedTasks := 0 for resultOfTheTask := range producedResults { //this loop will never finish because producedResults never gets closed // consolidate the results of the tasks executedTasks += resultOfTheTask }
Anda mahu menutup saluran selepas semua goroutine yang menulis kepadanya telah kembali. Anda boleh menggunakan WaitGroup untuk mencapai:
wg:=sync.WaitGroup{} for i := 0; i < quantityOfWorkers; i++ { wg.Add(1) go func() { defer wg.Done() for taskSize := range remainingTasks { //simulate a long task time.Sleep(time.Second * time.Duration(taskSize)) //return the result of the long task producedResults <- taskSize } }() } go func() { wg.Wait() close(producedResults) }()
Atas ialah kandungan terperinci Bagaimana untuk menutup saluran yang diisi oleh berbilang goroutine apabila semua kerja selesai?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!