当先锋百科网

首页 1 2 3 4 5 6 7


基于 Channel 编写一个简单的单线程生产者消费者模型: 队列: 队列长度 10,队列元素类型为 int 生产者: 每 1 秒往队列中放入一个类型为 int 的元素,消费者: 每一秒从队列中获取一个元素并打印。

1.生产者消费者问题

版本1 未添加wait控制

package main

import (
	"fmt"
	"time"
)

func product(ch chan int) {
	for {
		ch <- 1
		time.Sleep(time.Second)
		fmt.Println("ch put:", 1)
	}

}

func custom(ch chan int) {
	for v := range ch {
		time.Sleep(time.Second)
		fmt.Println("ch get:", v)
	}

}

func main() {
	fmt.Println("main start product and custom problom")
	ch := make(chan int, 10)
	go product(ch)
	go custom(ch)
	time.Sleep(30 * time.Second)

}

版本2 添加wait控制

package main

import (
	"fmt"
	"sync"
	"time"
)

func product(ch chan int, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		ch <- 1
		time.Sleep(time.Second)
		fmt.Println("ch put:", 1)
	}
}

func custom(ch chan int, wg *sync.WaitGroup) {
	defer wg.Done()
	for v := range ch {
		time.Sleep(time.Second)
		fmt.Println("ch get:", v)
	}
}

func main() {
	fmt.Println("main start product and custom problem")
	ch := make(chan int, 10)
	var wg sync.WaitGroup
	wg.Add(2)

	go product(ch, &wg)
	go custom(ch, &wg)

	wg.Wait()
	close(ch)
	fmt.Println("main exit")
}

版本3 不添加wait控制

package main

import (
	"fmt"
	"time"
)

func producer(queue chan int) {
	for i := 0; ; i++ {
		queue <- i
		fmt.Printf("product get %d\n", i)
		time.Sleep(time.Second)
	}
}

func consumer(queue chan int) {
	for {
		item := <-queue
		fmt.Printf("custom get  %d\n", item)
		time.Sleep(time.Second)
	}
}

func main() {
	queue := make(chan int, 10)

	go producer(queue)
	consumer(queue)
}

2.添加条件当channel为空或为满时阻塞

基于 Channel 编写一个简单的单线程生产者消费者模型: 队列: 队列长度 10,队列元素类型为 int 生产者: 每 1 秒往队列中放入一个类型为 int 的元素,队列满时输出product full 消费者: 每一秒从队列中获取一个元素并打印,队列为空时输出custom null。

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int, 10) // 设置缓冲区大小为1

	go func() {
		for i := 0; ; i++ {
			val := i
			select { //如果通道已经存满,就会执行 default
			// 写数据
			case ch <- val:
				fmt.Printf("put %d into channel\n", val)
				time.Sleep(500 * time.Millisecond)
			default:
				time.Sleep(time.Second)
				fmt.Println("channel full")

			}
		}
	}()

	for {
		select { //如果通道已经存满,就会执行 default
		// 写数据
		case val := <-ch:
			fmt.Printf("get %d out of channel\n", val)
			time.Sleep(time.Second)
		default:
			time.Sleep(time.Second)
			fmt.Println("channel null")

		}
	}
}