分享
  1. 首页
  2. 文章

go语言实现线程池

wolfred7464 · · 14681 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

话说真的好久没有写博客了,最近赶新项目,工作太忙了。这一周任务比较少,又可以随便敲敲了。

逛论坛的时候突发奇想,想用go语言实现一个线程池,主要功能是:添加total个任务到线程池中,线程池开启number个线程,每个线程从任务队列中取出一个任务执行,执行完成后取下一个任务,全部执行完成后回调一个函数。

不知道有没有卵用,但是我尝试用它开启3个线程,下载10个文件,效果还是不错的。第一次写这方面的东西,可能写得不好。

思路就是把任务放到channel里,每个线程不停的从channel中取出任务执行,并把执行结果写入另一个channel,当得到total个结果后,回调函数。

上一发代码:

 1 type GoroutinePool struct {
 2  Queue chan func() error
 3 Number int
 4 Total int
 5 
 6  result chan error
 7  finishCallback func()
 8 }
 9 
10 // 初始化
11 func (self *GoroutinePool) Init(number int, total int) {
12 self.Queue = make(chan func() error, total)
13 self.Number = number
14 self.Total = total
15 self.result = make(chan error, total)
16 }
17 
18 // 开门接客
19 func (self *GoroutinePool) Start() {
20 // 开启Number个goroutine
21 for i := 0; i < self.Number; i++ {
22  go func() {
23 for {
24 task, ok := <-self.Queue
25 if !ok {
26 break
27  }
28 
29 err := task()
30 self.result <- err
31  }
32  }()
33  }
34 
35 // 获得每个work的执行结果
36 for j := 0; j < self.Total; j++ {
37 res, ok := <-self.result
38 if !ok {
39 break
40  }
41 
42 if res != nil {
43  fmt.Println(res)
44  }
45  }
46 
47 // 所有任务都执行完成,回调函数
48 if self.finishCallback != nil {
49  self.finishCallback()
50  }
51 }
52 
53 // 关门送客
54 func (self *GoroutinePool) Stop() {
55  close(self.Queue)
56  close(self.result)
57 }
58 
59 // 添加任务
60 func (self *GoroutinePool) AddTask(task func() error) {
61 self.Queue <- task
62 }
63 
64 // 设置结束回调
65 func (self *GoroutinePool) SetFinishCallback(callback func()) {
66 self.finishCallback = callback
67 }

开启3个线程,下载10个文件的测试代码:

 1 func Download_test() {
 2 urls := []string{
 3 "http://dlsw.baidu.com/sw-search-sp/soft/44/17448/Baidusd_Setup_4.2.0.7666.1436769697.exe",
 4 "http://dlsw.baidu.com/sw-search-sp/soft/3a/12350/QQ_V7.4.15197.0_setup.1436951158.exe",
 5 "http://dlsw.baidu.com/sw-search-sp/soft/9d/14744/ChromeStandalone_V43.0.2357.134_Setup.1436927123.exe",
 6 "http://dlsw.baidu.com/sw-search-sp/soft/6f/15752/iTunes_V12.2.1.16_Setup.1436855012.exe",
 7 "http://dlsw.baidu.com/sw-search-sp/soft/70/17456/BaiduAn_Setup_5.0.0.6747.1435912002.exe",
 8 "http://dlsw.baidu.com/sw-search-sp/soft/40/12856/QIYImedia_1_06_v4.0.0.32.1437470004.exe",
 9 "http://dlsw.baidu.com/sw-search-sp/soft/42/37473/BaiduSoftMgr_Setup_7.0.0.1274.1436770136.exe",
10 "http://dlsw.baidu.com/sw-search-sp/soft/49/16988/YoudaoNote_V4.1.0.300_setup.1429669613.exe",
11 "http://dlsw.baidu.com/sw-search-sp/soft/55/11339/bdbrowserSetup-7.6.100.2089-1212_11000003.1437029629.exe",
12 "http://dlsw.baidu.com/sw-search-sp/soft/53/21734/91zhushoupc_Windows_V5.7.0.1633.1436844901.exe",
13  }
14 
15 pool := new(GoroutinePool)
16 pool.Init(3, len(urls))
17 
18 for i := range urls {
19 url := urls[i]
20  pool.AddTask(func() error {
21 return download(url)
22  })
23  }
24 
25 isFinish := false
26 
27  pool.SetFinishCallback(func() {
28 func(isFinish *bool) {
29 *isFinish = true
30 }(&isFinish)
31  })
32 
33  pool.Start()
34 
35 for !isFinish {
36 time.Sleep(time.Millisecond * 100)
37  }
38 
39  pool.Stop()
40 fmt.Println("所有操作已完成!")
41 }
42 
43 func download(url string) error {
44 fmt.Println("开始下载... ", url)
45 
46 sp := strings.Split(url, "/")
47 filename := sp[len(sp)-1]
48 
49 file, err := os.Create("/Users/staff/Documents/Red_Test/AAAA/" + filename)
50 if err != nil {
51 return err
52  }
53 
54 res, err := http.Get(url)
55 if err != nil {
56 return err
57  }
58 
59 length, err := io.Copy(file, res.Body)
60 if err != nil {
61 return err
62  }
63 
64 fmt.Println("## 下载完成! ", url, " 文件长度:", length)
65 return nil
66 }

使用起来还算可以的吧。。。


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:wolfred7464

查看原文:go语言实现线程池

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
14681 次点击 ∙ 1 赞
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏