Bagaimana untuk menyekat pengeluar dan pengguna daripada membaca mesej?

WBOY
Lepaskan: 2024-02-11 18:00:11
ke hadapan
830 orang telah melayarinya

Bagaimana untuk menyekat pengeluar dan pengguna daripada membaca mesej?

PHP editor Zimo Dalam proses pembangunan perisian, baris gilir mesej ialah mekanisme komunikasi biasa yang digunakan untuk mencapai komunikasi tak segerak antara pengeluar dan pengguna. Walau bagaimanapun, kadangkala kami ingin mengawal pembacaan mesej oleh pengeluar dan pengguna untuk mengurus sumber sistem dengan lebih baik dan mengendalikan permintaan semasa waktu sibuk. Artikel ini akan memperkenalkan beberapa kaedah untuk menyekat pengeluar dan pengguna daripada membaca mesej untuk membantu pembangun mengoptimumkan prestasi sistem dan meningkatkan kestabilan aplikasi.

Kandungan soalan

Saya ingin mendapatkan pengeluar aplikasi-pengguna (ditutup melalui isyarat) menggunakan go.

Pengeluar terus menjana mesej dalam baris gilir, dengan had 10. Sesetengah pengguna membaca dan memproses saluran. Jika bilangan mesej dalam baris gilir ialah 0, pengeluar menjana 10 mesej sekali lagi. Apabila isyarat berhenti diterima, pengeluar berhenti menjana mesej baharu dan pengguna memproses segala-galanya dalam saluran.

Saya menjumpai sekeping kod tetapi tidak dapat memahami sama ada ia berfungsi dengan betul kerana saya menemui sesuatu yang pelik:

  1. Mengapa selepas menghentikan program, tidak semua mesej dalam baris gilir diproses, dan beberapa data kelihatan hilang. (Dalam tangkapan skrin, 15 mesej telah dihantar tetapi 5 telah diproses)
  2. Bagaimana untuk mengehadkan baris gilir dengan betul kepada 10 mesej, iaitu perlu menulis 10 mesej, tunggu pemprosesan apabila pembilang baris gilir mencapai 0, dan kemudian tulis 10 lagi?
  3. Adakah mungkin untuk memberitahu penerbit selepas isyarat berhenti supaya dia tidak lagi menjana mesej baharu kepada saluran? (Dalam tangkapan skrin, pengeluar berjaya menulis ke baris gilir - 12,13,14,15)

Hasil:

Contoh kod:

package main import ( "context" "fmt" "math/rand" "os" "os/signal" "sync" "syscall" "time" ) func main() { const nConsumers = 2 in := make(chan int, 10) p := Producer{&in} c := Consumer{&in, make(chan int, nConsumers)} go p.Produce() ctx, cancelFunc := context.WithCancel(context.Background()) go c.Consume(ctx) wg := &sync.WaitGroup{} wg.Add(nConsumers) for i := 1; i <= nConsumers; i++ { go c.Work(wg, i) } termChan := make(chan os.Signal, 1) signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM) <-termChan cancelFunc() wg.Wait() } type Consumer struct { in *chan int jobs chan int } func (c Consumer) Work(wg *sync.WaitGroup, i int) { defer wg.Done() for job := range c.jobs { fmt.Printf("Worker #%d start job %d\n", i, job) time.Sleep(time.Millisecond * time.Duration(3000+rand.Intn(3000))) fmt.Printf("Worker #%d finish job %d\n", i, job) } fmt.Printf("Worker #%d interrupted\n", i) } func (c Consumer) Consume(ctx context.Context) { for { select { case job := <-*c.in: c.jobs <- job case <-ctx.Done(): close(c.jobs) fmt.Println("Consumer close channel") return } } } type Producer struct { in *chan int } func (p Producer) Produce() { task := 1 for { *p.in <- task fmt.Printf("Send value %d\n", task) task++ time.Sleep(time.Millisecond * 500) } }
Salin selepas log masuk

Penyelesaian

Mengapa selepas menghentikan program, tidak semua mesej dalam baris gilir diproses, dan beberapa data nampaknya hilang.

Ini kerana apabilactx完成后,(consumer).consume停止从in通道读取,但go p.produce()创建的 goroutine 仍然写入inch.

Demo di bawah menyelesaikan masalah ini dan memudahkan kod sumber.

Nota:

  1. producectx完成后停止。并且它关闭了inSaluran.

  2. Bidangjobs已从consumer中删除,工作人员直接从inBaca saluran.

  3. Permintaan berikut tidak diendahkan kerana pelik. Tingkah laku biasa ialah apabila kerja dijana, jika saluranin通道未满,则作业会立即发送到in通道;当它已满时,发送操作将阻塞,直到从inmembaca kerja itu sehingga itu.

    Jika bilangan mesej dalam baris gilir ialah 0, pengeluar menjana 10 mesej lagi

package main import ( "context" "fmt" "math/rand" "os/signal" "sync" "syscall" "time" ) func main() { const nConsumers = 2 ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() in := make(chan int, 10) p := Producer{in} c := Consumer{in} go p.Produce(ctx) var wg sync.WaitGroup wg.Add(nConsumers) for i := 1; i <= nConsumers; i++ { go c.Work(&wg, i) } <-ctx.Done() fmt.Printf("\nGot end signal, waiting for %d jobs to finish\n", len(in)) wg.Wait() } type Consumer struct { in chan int } func (c *Consumer) Work(wg *sync.WaitGroup, i int) { defer wg.Done() for job := range c.in { fmt.Printf("Worker #%d start job %d\n", i, job) time.Sleep(time.Millisecond * time.Duration(3000+rand.Intn(3000))) fmt.Printf("Worker #%d finish job %d\n", i, job) } fmt.Printf("Worker #%d interrupted\n", i) } type Producer struct { in chan int } func (p *Producer) Produce(ctx context.Context) { task := 1 for { select { case p.in <- task: fmt.Printf("Send value %d\n", task) task++ time.Sleep(time.Millisecond * 500) case <-ctx.Done(): close(p.in) return } } }
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana untuk menyekat pengeluar dan pengguna daripada membaca mesej?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!