1.现在有如下流程:
1.检测更新
2.选择版本
3.选择区服
4.登录游戏
如下图所示:
目前我想利用go语言进行4个线程并发进行检测,当完成其中某一个任务那么就停止当前及以前线程,如完成选择区服,停止检测更新,选择版本以及选择区服,我实在是想不到怎么搞合适,请教下各位大佬,谢谢
1.现在有如下流程:
1.检测更新
2.选择版本
3.选择区服
4.登录游戏
如下图所示:
目前我想利用go语言进行4个线程并发进行检测,当完成其中某一个任务那么就停止当前及以前线程,如完成选择区服,停止检测更新,选择版本以及选择区服,我实在是想不到怎么搞合适,请教下各位大佬,谢谢
你这四个步骤无法最终发起的都是网络请求,你可以使用context
来实现中断请求。
四个协程共用一个context
对象,当任何一个请求完成,调用cancel
方法中断其他的三个请求。
简单实现了一下同时处理4个任务,并且中断执行,
原理是 4个任务中必须带有同一个context. 并且需要实现 context.Done()
的监听
http包的req.WithContext里面是实现了该监听,因此可以通过上层执行 cancel()
来取消执行
如下代码,执行结果为:
2019/07/31 15:58:08 done: https://www.163.com
2019/07/31 15:58:08 3 <nil>
2019/07/31 15:58:08 2 Get https://www.baidu.com: context canceled
2019/07/31 15:58:08 1 Get https://www.google.com: context canceled
2019/07/31 15:58:08 4 Get https://www.taobao.com: context canceled
package main
import (
"context"
"log"
"net/http"
"sync"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
cancelCh := make(chan struct{})
var wg = sync.WaitGroup{}
wg.Add(4)
go func() {
defer wg.Done()
log.Println(1, Request(ctx, "https://www.google.com", cancelCh))
}()
go func() {
defer wg.Done()
log.Println(2, Request(ctx, "https://www.baidu.com", cancelCh))
}()
go func() {
defer wg.Done()
log.Println(3, Request(ctx, "https://www.163.com", cancelCh))
}()
go func() {
defer wg.Done()
log.Println(4, Request(ctx, "https://www.taobao.com", cancelCh))
}()
go func() {
<-cancelCh
cancel()
}()
wg.Wait()
}
func Request(ctx context.Context, url string, cancelCh chan struct{}) error {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err
}
req = req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
log.Println("done: ", url)
close(cancelCh)
return err
}
扩展阅读:
1 golang官方的errgroup
2 bilibili实现的errgroup
2 回答2.6k 阅读✓ 已解决
1 回答2.4k 阅读✓ 已解决
2 回答1.8k 阅读✓ 已解决
1 回答1.3k 阅读✓ 已解决
1 回答1.5k 阅读✓ 已解决
2 回答1.4k 阅读
1 回答1.8k 阅读
这个需要并发控制,实现方式有全局变量、channel、WaitGroup、context,可参考https://segmentfault.com/a/11...