go并发编程系列四:线程分组及控制线程的交替执行

背景:在上一篇中,作为班主任的你,对班级的管理初见成效,但理想和现实总有差距,理想情况下,从接手一个调皮的班级到班级的管理井井有条,是从0到1的跨越,没有中间的过渡阶段,然而,现实是:班级里少不了调皮的学生,对于这样的情况,应该怎么办呢?这篇文章讲解的正是现实中从0到1的过渡阶段,本文仅以讲解技术为出发点,不代表教育观点。

有一个万不得已的办法是:听话的学生和调皮的学生互不干扰。

对应为线程,就是对线程进行分组,按组执行。

在我们的假定场景中,张三、李四是听话的学生,自然是一组,王五是一组,三个学生需要完成一组任务,同时我们希望同一组的张三、李四交替完成任务。

我们把上述业务场景拆分为技术片段:张三、李四分组 + 张三、李四交替完成任务 + 王五单独一组 + 王五独自完成自己的任务

分组的概念很好理解,那么:张三、李四交替完成任务意味着什么呢?直白的说,就是张三、王五对应的线程不再各自持有互斥锁,变为普通线程,以便可以交替执行。

这里多说一点,线程的执行可以分为三个层级:1、交替执行 => 2、按序执行(竞争执行)=> 3、合作执行,本文我们讲的是第一个层级,即:交替执行。

为了进一步演示这个场景,我们引入了任务的工具类:init.go,代码如下:

package concurrent

var task = map[int]string{1:"起床", 2:"洗漱", 3:"吃饭"} // 班主任规定的一组任务

 

模拟班级的代码如下:

package concurrent

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

// 在这个例子里,我们希望王五不要捣乱,等张三和李四交替完成任务,王五再出现
// 即:张三和李四对应的线程先执行,王五对应的线程最后执行

func ThreadMutexImporveZhangSan(wg *sync.WaitGroup) {
    defer wg.Done()

    for i :=1; i <= 3; i++ {
        fmt.Println("张三:", task[i])
        time.Sleep(time.Millisecond * 500)
    }
}

func ThreadMutexImproveLiSi(wg *sync.WaitGroup) {
    defer wg.Done()

    for i := 1; i <= 3; i++ {
        fmt.Println("李四:", task[i])
        time.Sleep(time.Millisecond * 500)
    }
}

func ThreadMutexImproveWangWu() {
    for i := 1; i <= 3; i++ {
        fmt.Println("王五*:", task[i])
        time.Sleep(time.Millisecond * 500)
    }
}

 

为了适应线程分组,main.go的代码需要引入sync.WaitGroup,代码如下:

    wgImprove.Add(2)
    go concurrent.ThreadMutexImporveZhangSan(&wgImprove)
    go concurrent.ThreadMutexImproveLiSi(&wgImprove)
    wgImprove.Wait()
    go concurrent.ThreadMutexImproveWangWu()

此时,执行代码,可以看到张三、李四是一组的,并且是交替执行,王五是独立的,这也就意味着我们完成了班级的管理目标。

在下一篇文章中,我们将讲解第二个层级:按序执行。

posted @ 2023-09-02 16:07  jamstack  阅读(23)  评论(0编辑  收藏  举报