"Go language combat" study notes - buffered channel code combat

Chapter 6 Concurrency

6.5 channels

6.5.2 Buffered channels

concept

A buffered channel is a channel that can store one or more values ​​before being received. This
type of channel does not mandate that both sending and receiving must be done between goroutines. The conditions under which a channel can block send and receive actions are also different. The receive action will only block if there are no values ​​to receive in the channel. The send action will only block if the channel has no buffers available to hold the value being sent . This leads to a big difference between buffered and unbuffered channels: unbuffered channels guarantee that the sending and receiving goroutines will exchange data at the same time; buffered channels have no such guarantee .

Code combat

Let's look at an example using a buffered channel that manages a set of goroutines to receive and complete work.
Buffered channels provide a clear and intuitive way to do this, the code is as follows

// This sample program demonstrates how to use a buffered
// channel to work on multiple tasks with a predefined number
// of goroutines.
package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

const (
	numberGoroutines = 4  // Number of goroutines to use.
	taskLoad         = 10 // Amount of work to process.
)

// wg is used to wait for the program to finish.
var wg sync.WaitGroup

// init is called to initialize the package by the
// Go runtime prior to any other code being executed.
func init() {
	// Seed the random number generator.
	rand.Seed(time.Now().Unix())
}

// main is the entry point for all Go programs.
func main() {
	// Create a buffered channel to manage the task load.
	tasks := make(chan string, taskLoad)

	// Launch goroutines to handle the work.
	wg.Add(numberGoroutines)
	for gr := 1; gr <= numberGoroutines; gr++ {
		go worker(tasks, gr)
	}

	// Add a bunch of work to get done.
	for post := 1; post <= taskLoad; post++ {
		tasks <- fmt.Sprintf("Task : %d", post)
	}

	// Close the channel so the goroutines will quit
	// when all the work is done.
	close(tasks)

	// Wait for all the work to get done.
	wg.Wait()
}

// worker is launched as a goroutine to process work from
// the buffered channel.
func worker(tasks chan string, worker int) {
	// Report that we just returned.
	defer wg.Done()

	for {
		// Wait for work to be assigned.
		task, ok := <-tasks
		if !ok {
			// This means the channel is empty and closed.
			fmt.Printf("Worker: %d : Shutting Down\n", worker)
			return
		}

		// Display we are starting the work.
		fmt.Printf("Worker: %d : Started %s\n", worker, task)

		// Randomly wait to simulate work time.
		sleep := rand.Int63n(100)
		time.Sleep(time.Duration(sleep) * time.Millisecond)

		// Display we finished the work.
		fmt.Printf("Worker: %d : Completed %s\n", worker, task)
	}
}

operation result

go run listing24.go 
Worker: 1 : Started Task : 1
Worker: 3 : Started Task : 3
Worker: 4 : Started Task : 4
Worker: 2 : Started Task : 2
Worker: 3 : Completed Task : 3
Worker: 3 : Started Task : 5
Worker: 4 : Completed Task : 4
Worker: 4 : Started Task : 6
Worker: 1 : Completed Task : 1
Worker: 1 : Started Task : 7
Worker: 3 : Completed Task : 5
Worker: 3 : Started Task : 8
Worker: 1 : Completed Task : 7
Worker: 1 : Started Task : 9
Worker: 2 : Completed Task : 2
Worker: 2 : Started Task : 10
Worker: 4 : Completed Task : 6
Worker: 4 : Shutting Down
Worker: 3 : Completed Task : 8
Worker: 3 : Shutting Down
Worker: 2 : Completed Task : 10
Worker: 2 : Shutting Down
Worker: 1 : Completed Task : 9
Worker: 1 : Shutting Down

The Chinese comments and explanations of the specific codes are as follows

 

 

 

Guess you like

Origin blog.csdn.net/wangchao701123/article/details/123108122