Skip to the content.

场景描述

A方法中调用B方法和C方法,当A再次被调用时,如果上次的A方法还没执行完,则取消还在执行的A方法,并重新开始执行

思路

代码

package main

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

func main() {
	c := NewControl()
	go c.A()
	go c.A()
	time.Sleep(2500 * time.Millisecond)
	go c.A()
	time.Sleep(5 * time.Second)
}

type Control struct {
	Cancel context.CancelFunc
	mu     sync.Locker
}

func NewControl() *Control {
	return &Control{
		Cancel: nil,
		mu:     &sync.Mutex{},
	}
}

func (c *Control) A() {
	c.mu.Lock()
	if c.Cancel != nil {
		c.Cancel()
	}

	ctx, cancel := context.WithCancel(context.Background())
	c.Cancel = cancel
	c.mu.Unlock()

	wg := sync.WaitGroup{}

	wg.Add(3)
	go func() {
		defer wg.Done()
		c.B(ctx)
	}()
	go func() {
		defer wg.Done()
		c.C(ctx)
	}()

	go func() {
		defer wg.Done()
		select {
		case <-time.After(3 * time.Second):
			fmt.Println("Func A Done.")
		case <-ctx.Done():
			fmt.Println("Func A Cancel.")
		}
	}()

	wg.Wait()
}

func (c *Control) B(ctx context.Context) {
	select {
	case <-ctx.Done():
		fmt.Println("Func B Cancel.")
	case <-time.After(2 * time.Second):
		fmt.Println("Func B Done.")
	}
}

func (c *Control) C(ctx context.Context) {
	select {
	case <-ctx.Done():
		fmt.Println("Func C Cancel.")
	case <-time.After(3 * time.Second):
		fmt.Println("Func C Done.")
	}
}

输出

Func A Cancel.
Func C Cancel.
Func B Cancel.
Func B Done.
Func C Cancel.
Func A Cancel.
Func B Done.
Func C Done.
Func A Done.