13 线程(geroutine)和通道(channel)

一、线程(geroutine)

1.线程使用

package main

import (
	"fmt"
	"runtime"
	"time"
)

func geroutine(i int) {
	fmt.Printf("[%d]geroutine is called.\n", i)
}

func main() {
	runtime.GOMAXPROCS(6)

	for i := 0; i < 10; i++ {
		go geroutine(i)
	}

	time.Sleep(time.Second * 3)
}

输出结果:

[1]geroutine is called.
[9]geroutine is called.
[3]geroutine is called.
[0]geroutine is called.
[6]geroutine is called.
[4]geroutine is called.
[5]geroutine is called.
[8]geroutine is called.
[7]geroutine is called.
[2]geroutine is called.

2.等待线程结束WaitGroup

package main

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

var wg sync.WaitGroup

func geroutine(i int) {
	defer wg.Done()
	fmt.Printf("[%d]geroutine is called.\n", i)

	time.Sleep(time.Second * 3)
}

func main() {
	runtime.GOMAXPROCS(6)

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go geroutine(i)
	}

	//等待所有协程结束后退出
	wg.Wait()
}

3.通知geroutine退出[context]

package main

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

var wg sync.WaitGroup

func main() {
	ctx, cancle := context.WithCancel(context.Background())
	//开启一个线程
	wg.Add(1)
	go func(ctx context.Context) {
		defer wg.Done()
	EXIT:
		for {
			fmt.Println("geroutine is called.")
			time.Sleep(time.Second * 3)

			select {
			case <-ctx.Done():
				break EXIT
			default:
			}
		}
	}(ctx)

	time.Sleep(time.Second * 10)
	cancle() //10s后通知子线程退出

	//等待所有协程结束后退出
	wg.Wait()
}

二、通道(channel)

1.定义

//通道必须经过make初始化才能使用
func main() {
	var c chan int
	fmt.Println(c) //<nil>

}

2.初始化

func main() {
	var c chan int
	fmt.Println(c) //<nil>

	c = make(chan int)     //不带缓冲区通道的初始化
	c = make(chan int, 16) //带缓冲区通道的初始化
	fmt.Println(c)         //0xc000118000
}

3.通道的操作

package main

import (
	"fmt"
	"sync"
)

func main() {
	var ch = make(chan int, 10)
	var wg sync.WaitGroup

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			//接收 从通道接收数据
			x := <-ch
			fmt.Println(x)
		}()
	}

	//发送 将数据放入通道
	//循环写通道:for v := range ch
	for v := 0; v < 10; v++ {
		ch <- v * v //数据:索引的平方
	}

	wg.Wait()
	close(ch) //关闭通道
}

输出信息:

49
25
36
64
81
0
1
4
9
16

4.单向通道

func main() {
	//接收通道,不能发送
	ch1 := make(<-chan int, 10)
	x := <-ch1
	fmt.Println(x)

	//发送通道,不能接收
	ch2 := make(chan<- int, 10)
	ch2 <- 1
}

5.关键字select

func main() {
	ch := make(chan int, 5)

	/*
		select
		1.哪个分支不阻塞执行哪个分支
		2.所有可以执行的分支随机选择一个分支执行
	*/
	for i := 0; i < 10; i++ {
		select {
		case x := <-ch:
			fmt.Println(x)
		case ch <- i:
		}
	}
}

三、work pool

package main

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

var wg sync.WaitGroup

func worker(jobs <-chan int) {
	defer wg.Done()
	for x := range jobs {
		time.Sleep(time.Second * 3)

		fmt.Println("任务", x, "执行结果:", x*2)
	}
}

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

	//开启3个线程
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go worker(ch)
	}

	//执行10个任务
	for i := 0; i < 10; i++ {
		ch <- i
	}

	close(ch) //关闭后读取线程还能继续读取通道数据
	wg.Wait()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值