gy123
V2EX  ›  问与答

通过这段 Golang 代码,有点疑问

  •  
  •   gy123 · Dec 24, 2021 · 1861 views
    This topic created in 1784 days ago, the information mentioned may be changed or developed.

    以下代码可以做到所有协程睡眠 3 秒后直接输出;

    楼主是写 java 的,在想 java 要怎么能实现 go 通过协程实现的这个例子呢? (1)直接使用 100000 个线程执行,那内存占用和上下文切换太恐怖; (2)使用线程池一类的,参数设置不到位,根据原理只能一部分一部分执行,想全部执行,得参考(1)的线程数量...

    有啥能实现吗?难道类似这就是 go 协程的魅力?

    package main
    
    import (
    	"strconv"
    	"time"
    )
    
    func say0(str string) {
    	time.Sleep(3 * time.Second)
    	println(str)
    }
    
    func main() {
    	for i := 0; i < 100000; i++ {
    		go say0("协程" + strconv.Itoa(i))
    	}
    
    	time.Sleep(1000 * time.Second)
    }
    
    
    meiyoumingzi6
    meiyoumingzi6
    Dec 24, 2021 via iPhone
    1
    其实楼主写的这段代码有大坑🤪
    这里 go 不是直接就执行了,所以等到执行的时候 i 的数值是不确定的,另外因为这个 go 执行的太短了,所以在 1000 秒(对不起我一开始看成了 1000 毫秒)是可以执行完的,但是这样是不对的,应该使用 wait group 来处理这个事情,最后 可以无脑 go 吗?理论上来说是可以开启无限个的,但是开太多调度就会很繁忙,还有如果是并发处理请求的话,可能会给对方打挂了,还有一个就是 go 的 func 如果 panic 就会导致整个进程挂掉,所以最好是启动的时候 recover 一下






    回到问题上,如果让我换个语言,我会选择线程池,配合 queue 来做😁
    leon0318
    leon0318
    Dec 24, 2021 via iPhone
    2
    楼主有没有想过协程的应用场景? 照你这么说,java 早被打趴下了,然而……🐶
    anonymousar
    anonymousar
    Dec 24, 2021
    3
    线程池怎么就做不到了? push 100k 个 task/future 进去不就行了? 这跟线程数有啥关系? go 难道不用 thread 跑任务了?
    watzds
    watzds
    Dec 24, 2021
    4
    我理解就是应用层线程,应用层自己实现

    直接用普通线程池,任务互相的话依赖容易死锁,或者阻塞浪费资源,用 java 8 ForkJoinPool 好点
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    5
    @meiyoumingzi6 学习了
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    6
    @anonymousar push 到队列?然而每次拿出来多少任务执行,还是依靠设置的线程数吧。我知道 go 也是线程,但是这个场景你能做出来吗。可以写写试试
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    7
    @watzds 就是我写的这个例子,不知道 java 怎么实现
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    8
    我就想知道 java 怎么保证线程数很少的情况下,得到 go 执行的效果。。
    iamzuoxinyu
    iamzuoxinyu
    Dec 24, 2021
    9
    其实跟你自己实现个带任务窃取的线程池是一样的。
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    10
    @anonymousar 还是说你想表达的是用延迟线程池,设置个延迟时间然后队列里的任务全部执行。。
    gy123
    gy123
    OP
    Dec 24, 2021 via iPhone
    11
    @leonme 场景可能就是大 io 处理上,就算很多轻量级协程,要比线程好太多吧
    leon0318
    leon0318
    Dec 24, 2021 via iPhone
    12
    @gy123 然后你再想下正常业务瓶颈是在 io 上还是在 cpu 的调度(线程数)上? 所以你就明白为啥 go 一般都是做些网关代理中间件啥的
    gy123
    gy123
    OP
    Dec 24, 2021
    13
    @leonme 嗯,这里的 io 特指网络 io.受教了
    gy123
    gy123
    OP
    Dec 24, 2021
    14
    此贴终结...楼主忘记了 ScheduledExecutorService
    gy123
    gy123
    OP
    Dec 24, 2021
    15
    或者自己实现类似于拿出任务判断时间....被 go 这种 sleep 写法迷惑了
    anonymousar
    anonymousar
    Dec 24, 2021
    16
    @gy123 延迟跟队列跟线程池都无关 io 密集型任务 goroutine 就好处理么? 明明 epoll 才更优
    meiyoumingzi6
    meiyoumingzi6
    Dec 24, 2021
    17
    #1
    emmm 上面说的有点问题, 你这里是传的参数 , 所以 str 不会有问题

    @gy123
    无脑 go 版本
    ```golang
    package main

    import (
    "fmt"
    "strconv"
    "sync"
    "time"
    )

    func say0(str string, wg *sync.WaitGroup) {
    defer func() {
    _ = recover()
    // 处理异常
    wg.Done()
    }()
    time.Sleep(3 * time.Second)
    fmt.Println(str)
    }

    func main() {
    wg := &sync.WaitGroup{}
    for i := 0; i < 100000; i++ {
    wg.Add(1)
    go say0("协程" + strconv.Itoa(i), wg)
    }
    wg.Wait()

    }
    ```


    控制协程数量版本

    ```golang
    package main

    import (
    "fmt"
    "strconv"
    "sync"
    "time"
    )

    func say0(c chan int, wg *sync.WaitGroup) {
    defer func() {
    _ = recover()
    // 处理异常
    wg.Done()
    }()
    for {
    time.Sleep(1 * time.Second)
    i, ok := <-c
    if ok {
    fmt.Println("协程" + strconv.Itoa(i))
    } else {
    fmt.Println("协程结束")
    break
    }
    }

    }

    func main() {
    var c chan int
    c = make(chan int, 10)
    wg := &sync.WaitGroup{}
    for i := 0; i < 10; i++ {
    wg.Add(1)
    go say0(c, wg)
    }
    for i := 0; i < 100; i++ {
    c <- i
    }
    close(c)
    fmt.Printf("close")
    wg.Wait()
    }

    ```
    gy123
    gy123
    OP
    Dec 25, 2021 via iPhone
    18
    [ [码上开学] 到底什么是「非阻塞式」挂起?协程真的比线程更轻量级吗?-哔哩哔哩] https://b23.tv/YyQhA3Q

    我悟了,最后一段说的,的确就是我的误解
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4054 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 09:35 · PVG 17:35 · LAX 01:35 · JFK 04:35
    ♥ Do have faith in what you're doing.