zoukankan      html  css  js  c++  java
  • WorkPool线程池

    WorkPool线程池

    就是限制函数的运行数量的struct

    参考https://jiajunhuang.com/articles/2020_04_21-golang_concurrency.md.html

    package pool
    
    type GoPool struct {
    	MaxLimit int
    
    	tokenChan chan struct{}
    }
    
    type GoPoolOption func(*GoPool)
    
    func WithMaxLimit(max int) GoPoolOption {
    	return func(gp *GoPool) {
    		gp.MaxLimit = max
    		gp.tokenChan = make(chan struct{}, gp.MaxLimit)
    
    		for i := 0; i < gp.MaxLimit; i++ {
    			gp.tokenChan <- struct{}{}
    		}
    	}
    }
    
    func NewGoPool(options ...GoPoolOption) *GoPool {
    	p := &GoPool{}
    	for _, o := range options {
    		o(p)
    	}
    
    	return p
    }
    
    // Submit will wait a token, and then execute fn
    func (gp *GoPool) Submit(fn func()) {
    	token := <-gp.tokenChan // if there are no tokens, we'll block here
    
    	go func() {
    		fn()
    		gp.tokenChan <- token
    	}()
    }
    
    // Wait will wait all the tasks executed, and then return
    func (gp *GoPool) Wait() {
    	for i := 0; i < gp.MaxLimit; i++ {
    		<-gp.tokenChan
    	}
    
    	close(gp.tokenChan)
    }
    
    func (gp *GoPool) size() int {
    	return len(gp.tokenChan)
    }
    

    实现原理

    池子里面的属性是令牌桶,这个桶子用有缓冲chan来实现,实现了自动阻塞

    带有接口那味的实现

    workpool.go

    package work
    
    // 什么是池子,池子就是他一直有地址空间,你上传就Ok了
    // 方法:
    // 上传 + 执行任务
    // 当前任务空闲
    // 属性: 令牌桶
    type IWorkPool interface {
    	Submit(work IWork)
    	GetWorkCount() int
    }
    
    type WorkPool struct {
    	Tocken chan int
    }
    
    func NewWorkPool(limit int) *WorkPool {
    	wp := &WorkPool{
    		Tocken:make(chan int, limit),
    	}
    	for i := 0; i < limit; i++ {
    		wp.Tocken<- i
    	}
    	return  wp
    }
    
    func (wp *WorkPool) Submit(work IWork) {
    	<- wp.Tocken
    	go func() {
    		work.DoWork()
    		wp.Tocken<-1
    	}()
    }
    
    func (wp *WorkPool) GetWorkCount() int {
    	return len(wp.Tocken)
    }
    

    work.go

    package work
    
    import "fmt"
    
    // 属性:
    // work func()
    //方法:
    // DoWork()
    type IWork interface {
    	DoWork()
    }
    
    // 具体任务
    type Work struct {
    	work func()
    }
    
    func NewWork(fn func()) *Work {
    	return &Work{
    		work: fn,
    	}
    }
    
    func (w *Work) DoWork() {
    	w.work()
    	fmt.Println("任务ok")
    }
    

    测试代码

    package main
    
    import (
    	"go-newbase/work"
    	"time"
    )
    
    func main() {
    	pool := work.NewWorkPool(4)
    	for i := 0; i < 100; i++ {
    		newWork := work.NewWork(func() {
    			time.Sleep(3 * time.Second)
    		})
    		pool.Submit(newWork)
    	}
    
    	//time.Sleep(time.Second * 3)
    	time.Sleep(10000 * time.Second)
    }
    
  • 相关阅读:
    046 Android 给app加入百度地图
    007 Android newsClient 小实例应用
    IntelliJ IDEA(Android Studio)设置代码的快捷编辑模板Live Templates
    006 Android 利用apache tomcat在自己的电脑上搭建服务器
    005 Android HttpURLConnection的使用+Handler的原理及典型应用
    004 Andriod ListView组件的使用
    spd更改标题点击链接路径到编辑页面
    以下修改a标签的href链接和修改文字的代码
    域名不能访问,ip能访问就是dns
    删除web部件
  • 原文地址:https://www.cnblogs.com/maomaomaoge/p/14130026.html
Copyright © 2011-2022 走看看