Saya hanya mahu mencipta beberapa rutin pergi, katakan 5, tetapi saya boleh menerima bilangan pekerjaan yang berubah-ubah.
Berikut ialah kod yang saya cuba lakukan ini dengan ujian di bawahnya.
package main import ( "context" "fmt" "runtime" "time" ) func dowork(size int, capacity int) int { start := time.now() jobs := make(chan *job, capacity) results := make(chan *job, capacity) sem := make(chan struct{}, capacity) go chanworker(jobs, results, sem) for i := 0; i < size; i++ { jobs <- &job{id: i} } close(jobs) successcount := 0 for i := 0; i < size; i++ { item := <-results if item.result { successcount++ } fmt.printf("job %d completed %v\n", item.id, item.result) } close(results) close(sem) fmt.printf("time taken to execute %d jobs with %d capacity = %v\n", size, capacity, time.since(start)) return successcount } func chanworker(jobs <-chan *job, results chan<- *job, sem chan struct{}) { for item := range jobs { it := item sem <- struct{}{} fmt.printf("job %d started\n", it.id) go func() { timeoutctx, cancel := context.withtimeout(context.background(), 300*time.millisecond) defer cancel() time.sleep(time.duration(it.id) * 100 * time.millisecond) select { case <-timeoutctx.done(): fmt.printf("job %d timed out\n", it.id) it.result = false results <- it <-sem return default: fmt.printf("total number of routines %d\n", runtime.numgoroutine()) it.result = true results <- it <-sem } }() } }
Ujian tentang ini
package main import ( "testing" ) func Test_doWork(t *testing.T) { type args struct { size int capacity int } tests := []struct { name string args args want int }{ { name: "jobs 10 capacity 5", args: args{ size: 10, capacity: 5, }, want: 3, }, { name: "jobs 100 capacity 5", args: args{ size: 100, capacity: 5, }, want: 3, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := doWork(tt.args.size, tt.args.capacity); got < tt.want { t.Errorf("doWork() = %v, want %v", got, tt.want) } }) } }
Ujian jobs 10 容量 5
有效,但 jobs 100 容量 5
gagal.
Jika saya menetapkan kapasiti 50 untuk 100 kerja ia berfungsi tetapi tidak untuk 30 kerja dan tidak dapat memahami kelakuannya.
Berikut ialah pemahaman saya tentang saluran dan jangkaan saya bahawa ia akan berjaya.
Saluran penimbal, jika penuh, akan disekat sehingga beberapa kapasiti percuma tersedia. Saya menjangkakan bahawa sebaik sahaja saluran kerja penuh ia akan menyekat sehingga pekerja chanworker membebaskan sebahagian daripadanya. Pekerja chanworker itu sendiri menerima kapasiti dan menggunakan struktur kosong untuk memastikan tidak lebih daripada 5 utas pekerja dibuat.
Mengapa saya mendapat ralat
Ralat maut: Semua gorouti sedang tidur - kebuntuan!
? 致命错误:所有 goroutine 都在休眠 - 死锁!
?
由于主 goroutine 在所有作业都发送到 jobs
之前不会从 results
接收值,因此工作线程会在发送到 results
时阻塞。主 goroutine 阻止发送到 jobs
hasil
sehingga semua kerja dihantar ke pekerjaan</code >, Jadi benang pekerja menyekat semasa menghantar ke <code>hasil
. Goroutine utama menyekat penghantaran ke jobs
kerana kerja itu disekat. kebuntuan! Dibetulkan dengan menggunakan goroutine untuk melakukan kerja.
go func() { for i := 0; i < size; i++ { jobs <- &Job{id: i} } close(jobs) }()
Atas ialah kandungan terperinci Semua goroutine sedang tidur - kebuntuan, pada saluran buffer, tidak faham mengapa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!