这段goalng代码还能优化吗?

代码如下:

func main() {
    currentTaskNumber := 0
    maxTaskNumber := 3

    yourJob := func(url string) {
        defer func() {
            currentTaskNumber--
        }()

        time.Sleep(time.Second * 5)
    }

    sites := []string{"1111", "2222", "3333"}

    currentSiteIndex := 0

    getUrl := func() string {
        site := sites[currentSiteIndex]
        if currentSiteIndex < (len(sites) - 1) {
            currentSiteIndex++
        }else {
            currentSiteIndex = 0
        }
        return site
    }

    for true {
        if currentTaskNumber < maxTaskNumber {
            currentTaskNumber++
            go yourJob(getUrl())
        }
    }
}

希望能指点一下,谢谢了

讨论数量: 5
Dennis_Ritchie

多go-routine运行的情况下,变量的使用一定要加锁 :blush:

2年前 评论
sreio

这段代码什么作用,没看明白 ps:golang初学者

2年前 评论

1 没考虑并发安全 2 for一直在空跑

我下面写的,考虑到了这两个问题:

package main

import (
    "fmt"
    "time"
)

func main() {
    maxTaskNumber := 3
    taskChan := make(chan interface{}, maxTaskNumber)

    yourJob := func(url string) {
        defer func() {
            <-taskChan
        }()
        fmt.Printf("site:%s\n", url)
        time.Sleep(time.Second * 5)
    }

    // 并发安全产生处理的site
    sites := []string{"1111", "2222", "3333"}

    currentSiteIndex := 0

    urlChan := make(chan string)
    getUrl := func() {
        site := sites[currentSiteIndex]
        if currentSiteIndex < (len(sites) - 1) {
            currentSiteIndex++
        } else {
            currentSiteIndex = 0
        }
        urlChan <- site
    }

    go func() {
        for {
            getUrl()
        }
    }()

    // 启动同时运行指定个数的job
    for {
        // 获取启动新job的资格
        taskChan <- true
        // 并发安全获取url
        url := <-urlChan
        // 启动新job
        go yourJob(url)
    }
}
2年前 评论

我写了一个简版实现处理每个 site 任务, 所有代码没有实际跑起来只是在编辑器中按思路写了一下,希望能对你有启发。思路看代码应该还是很容易理解的。

主要优化有,将匿名函数变量用函数定义的方式书写。

使用 WaitGroup 做并发任务管理

import (
    "sync"
    "fmt"
)

wg := sync.WaitGroup
sites := []string{"1111", "2222", "3333"}


func main() {
    // 为每个 site 开一个 goroutine
    for site := range sites {
        wg.Add(1)
        go yourJob(site)
    }
    wg.Wait()

    fmt.Println("Done")
}

func yourJob(url string) {
    defer func ()  {
        wg.Done()
    }()
}

如果您想要有 max 值做协程多少的管理,我觉得可以这样写:

import (
    "sync"
    "fmt"
)

maxTaskNum := 3
sites := [maxTaskNumber]string{"1111", "2222", "3333"}
wg := sync.WaitGroup

func main() {

    // 按设置 max 值开固定个数的 goroutine
    for i:=0; i<maxTaskNum; i++ {
        wg.Add(1)
        go yourJob(i)
    }
    wg.Wait()

    fmt.Println("Done")
}

func yourJob(index int) {
    // 每个 goroutine 按 max 值遍历切片中数据
    for ;index < len(sites); index = index+maxTaskNum {
        handle(sites[index])
    }
    wg.Done()
}

func handle(site string) {
    fmt.Println("Do someting here in site:", site)
}
2年前 评论
package main

import (
    "fmt"
    "time"
)

func main() {
    maxTaskNumber := 3
    taskNumber := make(chan int, maxTaskNumber)

    //单向channel获取数据
    yourJob := func(taskNumber <-chan int, urlChan <-chan string) {
        //更新目前协程数量
        defer func() {
            <-taskNumber
        }()
        fmt.Println(<-urlChan)
        time.Sleep(time.Second * 5)
    }

    sites := []string{"1111", "2222", "3333"}

    currentSiteIndex := 0
    urlChan := make(chan string)
    //循环获取sites内字符串,通过单向channel发送数据
    getUrl := func(urlChan chan<- string) {
        urlChan <- sites[currentSiteIndex]
        //下标通过取余更新
        currentSiteIndex = (currentSiteIndex + 1) % len(sites)
    }

    go func() {
        for {
            getUrl(urlChan)
        }
    }()

    for {
        //控制协程数量,超过最大数量将阻塞等待
        taskNumber <- 1
        go yourJob(taskNumber, urlChan)
    }
}
2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!