Golang并发处理任务示例

假设我有30个任务,每个任务的处理时间大概要2秒,如果用传统的非并发的代码来写大概三十个任务要60秒(1分钟才能执行完),如果用上Golang的goroutine来写大概只要4秒

package main

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

type Pool struct {
	queue chan int
	wg    *sync.WaitGroup
}

// 创建并发控制池, 设置并发数量与任务总数量
func NewPool(cap, total int) *Pool {
	if cap < 1 {
		cap = 1
	}
	p := &Pool{
		queue: make(chan int, cap),
		wg:    new(sync.WaitGroup),
	}
	p.wg.Add(total)
	return p
}

// 向并发队列中添加一个
func (p *Pool) AddOne() {
	p.queue <- 1
}

// 并发队列中释放一个, 并从任务总数量中减去一个
func (p *Pool) DelOne() {
	<-p.queue
	p.wg.Done()
}

func main() {
	//开启多核处理
	runtime.GOMAXPROCS(runtime.NumCPU())
	//需要处理的下载任务
	urls := []string{
		"01", "02", "03", "04", "05", "06",
		"07", "08", "09", "10", "11", "12",
		"13", "14", "15", "16", "17", "18",
		"19", "20", "21", "22", "23", "24",
		"25", "26", "27", "28", "29", "30",
	}
	//初始化一个控制池,设置并发数量20
	pool := NewPool(20, len(urls))
	//计算执行时间
	now:=time.Now()
	//并发处理
	for _, v := range urls {
		go func(url string) {
			pool.AddOne() // 向并发控制池中添加一个, 一旦池满则此处阻塞
			//任务处理
			err := Download(url)
			if nil != err {
				println(err)
			}
			pool.DelOne() // 从并发控制池中释放一个, 之后其他被阻塞的可以进入池中
		}(v)
	}
	//等待所有下载全部完成
	pool.wg.Wait()
	//计算执行时间
	next:=time.Now()
	fmt.Println("执行时间:",next.Sub(now))
}

func Download(s string) error {
	//下载测试
	time.Sleep(2*time.Second)
	//这里下载可以做一些并发时锁的使用
	println("任务ID:",s)
	return nil
}

这份代码开启了golang的多核处理,并设置并发数量为20,每个任务的执行时间为2秒(这里用time的延迟函数来模拟),并打印出执行时间。下图是执行时间,执行时间可根据服务器的配置和调整并发数量而改变。

QQ截图20170609145453.png

Comments : 1

有问题可在下面发表评论,当然没事也可以在下面吹吹牛皮、扯扯淡!
  1. 回复
    这个是任务量已知的情况,如果我不知道urls的数量,他是从另一个传过来的,怎样才能干完活自己退出呢。

发表评论

*