go语言实现线程池
话说真的好久没有写博客了,最近赶新项目,工作太忙了。这一周任务比较少,又可以随便敲敲了。
逛论坛的时候突发奇想,想用go语言实现一个线程池,主要功能是:添加total个任务到线程池中,线程池开启number个线程,每个线程从任务队列中取出一个任务执行,执行完成后取下一个任务,全部执行完成后回调一个函数。
不知道有没有卵用,但是我尝试用它开启3个线程,下载10个文件,效果还是不错的。第一次写这方面的东西,可能写得不好。
思路就是把任务放到channel里,每个线程不停的从channel中取出任务执行,并把执行结果写入另一个channel,当得到total个结果后,回调函数。
上一发代码:
type GoroutinePool struct {
Queue chan func() error
Number int
Total int
result chan error
finishCallback func()
}
// 初始化
func (self *GoroutinePool) Init(number int, total int) {
self.Queue = make(chan func() error, total)
self.Number = number
self.Total = total
self.result = make(chan error, total)
}
// 开门接客
func (self *GoroutinePool) Start() {
// 开启Number个goroutine
for i := ; i < self.Number; i++ {
go func() {
for {
task, ok := <-self.Queue
if !ok {
break
}
err := task()
self.result <- err
}
}()
}
// 获得每个work的执行结果
for j := ; j < self.Total; j++ {
res, ok := <-self.result
if !ok {
break
}
if res != nil {
fmt.Println(res)
}
}
// 所有任务都执行完成,回调函数
if self.finishCallback != nil {
self.finishCallback()
}
}
// 关门送客
func (self *GoroutinePool) Stop() {
close(self.Queue)
close(self.result)
}
// 添加任务
func (self *GoroutinePool) AddTask(task func() error) {
self.Queue <- task
}
// 设置结束回调
func (self *GoroutinePool) SetFinishCallback(callback func()) {
self.finishCallback = callback
}
开启3个线程,下载10个文件的测试代码:
func Download_test() {
urls := []string{
"http://dlsw.baidu.com/sw-search-sp/soft/44/17448/Baidusd_Setup_4.2.0.7666.1436769697.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/3a/12350/QQ_V7.4.15197.0_setup.1436951158.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/9d/14744/ChromeStandalone_V43.0.2357.134_Setup.1436927123.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/6f/15752/iTunes_V12.2.1.16_Setup.1436855012.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/70/17456/BaiduAn_Setup_5.0.0.6747.1435912002.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/40/12856/QIYImedia_1_06_v4.0.0.32.1437470004.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/42/37473/BaiduSoftMgr_Setup_7.0.0.1274.1436770136.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/49/16988/YoudaoNote_V4.1.0.300_setup.1429669613.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/55/11339/bdbrowserSetup-7.6.100.2089-1212_11000003.1437029629.exe",
"http://dlsw.baidu.com/sw-search-sp/soft/53/21734/91zhushoupc_Windows_V5.7.0.1633.1436844901.exe",
}
pool := new(GoroutinePool)
pool.Init(, len(urls))
for i := range urls {
url := urls[i]
pool.AddTask(func() error {
return download(url)
})
}
isFinish := false
pool.SetFinishCallback(func() {
func(isFinish *bool) {
*isFinish = true
}(&isFinish)
})
pool.Start()
for !isFinish {
time.Sleep(time.Millisecond * )
}
pool.Stop()
fmt.Println("所有操作已完成!")
}
func download(url string) error {
fmt.Println("开始下载... ", url)
sp := strings.Split(url, "/")
filename := sp[len(sp)-]
file, err := os.Create("/Users/staff/Documents/Red_Test/AAAA/" + filename)
if err != nil {
return err
}
res, err := http.Get(url)
if err != nil {
return err
}
length, err := io.Copy(file, res.Body)
if err != nil {
return err
}
fmt.Println("## 下载完成! ", url, " 文件长度:", length)
return nil
}
使用起来还算可以的吧。。。
go语言实现线程池的更多相关文章
- C语言实现线程池功能
1. 线程池基本原理 2. 线程池C语言实现 2.1 线程池的数据结构 #include <stdio.h> #include <pthread.h> #include < ...
- C语言实现线程池
以前写过一篇关于如何使用多线程推升推送速度(http://www.cnblogs.com/bai-jimmy/p/5177433.html),能够到达5000qps,其实已经可以满足现在的业务,不过在 ...
- 用go语言实现线程池
代码放在 https://github.com/bigben0123/workerPool 安装完go软件后.执行目录中的install.cmd即可.
- C语言实现简单线程池(转-Newerth)
有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池.下面是一个C语言实现的简单的线程池. 头文件: 1: #ifndef THREAD_POOL ...
- linux下c语言实现简单----线程池
这两天刚好看完linux&c这本书的进程线程部分,学长建议可以用c语言实现一个简单的线程池,也是对线程知识的一个回顾与应用.线程的优点有好多,它是"轻量级的进程",所需资源 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第5节 线程池_1_线程池的概念和原理
线程的底层原理 集合有很多种,线程池的集合用LinkedList最好
- 01 语言基础+高级:1-7 异常与多线程_day07 【线程池、Lambda表达式】
day07[线程池.Lambda表达式] 主要内容 等待与唤醒案例 线程池 Lambda表达式 教学目标 -[ ] 能够理解线程通信概念-[ ] 能够理解等待唤醒机制-[ ] 能够描述Java中线程池 ...
- Linux杂谈: 实现一种简单实用的线程池(C语言)
基本功能 1. 实现一个线程的队列,队列中的线程启动后不再释放: 2. 没有任务执行时,线程处于pending状态,等待唤醒,不占cpu: 3. 当有任务需要执行时,从线程队列中取出一个线程执行任务: ...
- github上使用C语言实现的线程池
网上介绍线程池的知识很多,但是在代码实现上介绍的又不是那么多.而且给人的一种感觉就是:你的这种实现是正规的方式还是你自己的实现? 如果有这么个疑问,且想找一个靠谱的代码拿来使用,那么这个项目是个不错的 ...
随机推荐
- FTP服务详解
FTP服务 本章机构 简介 File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文件传输协议".用于Internet上的控制文件的双向传输.同时, ...
- H.264编码之DCT变换原理
DCT变换是一种与FFT变换紧密相连的数学运算,当函数为偶函数是,其傅立叶展开式只有余弦项,因些称为余弦变换,其离散化的过程称为DCT(离散余弦)变换.下面我们就推导下H.264的4x4整数DCT公式 ...
- Redux你的Angular 2应用--ngRx使用体验
Angular2和Rx的相关知识可以看我的Angular 2.0 从0到1系列第一节:Angular 2.0 从0到1 (一)第二节:Angular 2.0 从0到1 (二)第三节:Angular 2 ...
- C++STL学习笔记_(4)queue
10.2.5Queue容器 Queue简介 ² queue是队列容器,是一种"先进先出"的容器. ² queue是简单地装饰deque容器而成为另外的一种容器. ² #inc ...
- Java Concurrency - 线程的基础操作
创建线程 在 Java 中,创建线程有两种方式: 继承 java.lang.Thread 类,重写 run 方法. public class MyJob extends Thread { @Overr ...
- Jquery中bind和live的区别
Jquery中绑定事件有三种方法:以click事件为例 (1)target.click(function(){}); (2)target.bind("click",function ...
- sqlserver 关于快照
数据库快照:是数据库某一时间点的视图,快照涉及最初目的是为了报表服务,快照还可以和镜像结合来达到读写分离的目的 数据库快照:是sqlserver数据库的只读静态视图快照的作用:1 提供了一个静态的视图 ...
- Contoso 大学 - 8 – 实现继承
原文 Contoso 大学 - 8 – 实现继承 By Tom Dykstra, Tom Dykstra is a Senior Programming Writer on Microsoft's W ...
- Cocoa 框架为什么采用两阶段的方式来创建对象?
对于之前一直使用C#语言的我来说,刚开始接触Objective-c来创建对象时很迷惑,为何创建对象一般情况下需要通过发送两个消息(调用两个方法)才能创建一个类实例对象(例如[[UIButton all ...
- js 获取 当前时间 时间差 时间戳 倒计时
开发web一段时间后发现经常使用时间进行一些操作,比较多的就是获取当前时间.对时间进行比较.时间倒计时.时间戳这些部分,每次去用经常忘总是需要去查询,还是自己总结一下比较靠谱. 获取时间戳的方法: 第 ...