2 回答
TA贡献1824条经验 获得超8个赞
如果您只需要同时运行 n 个 goroutine,您可以拥有一个大小为 n 的缓冲通道,并在没有剩余空间时使用它来阻止创建新的 goroutine,就像这样
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
const ROUTINES = 2
rand.Seed(time.Now().UnixNano())
stopper := make(chan struct{}, ROUTINES)
var counter int
for {
counter++
stopper <- struct{}{}
go func(c int) {
fmt.Println("+ Starting goroutine", c)
time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
fmt.Println("- Stopping goroutine", c)
<-stopper
}(counter)
}
}
在这个例子中,你会看到你只能拥有 ROUTINES 个存活时间为 0、1 或 2 秒的 goroutine。在输出中,您还可以看到每次一个 goroutine 结束时另一个 goroutine 是如何开始的。
TA贡献1813条经验 获得超2个赞
这增加了一个外部依赖,但考虑这个实现:
package main
import (
"context"
"database/sql"
"log"
"github.com/MicahParks/ctxerrpool"
)
func main() {
// Create a pool of 2 workers for database queries. Log any errors.
databasePool := ctxerrpool.New(2, func(_ ctxerrpool.Pool, err error) {
log.Printf("Failed to execute database query.\nError: %s", err.Error())
})
// Get a list of queries to execute.
queries := []string{
"SELECT first_name, last_name FROM customers",
"SELECT price FROM inventory WHERE sku='1234'",
"other queries...",
}
// TODO Make a database connection.
var db *sql.DB
for _, query := range queries {
// Intentionally shadow the looped variable for scope.
query := query
// Perform the query on a worker. If no worker is ready, it will block until one is.
databasePool.AddWorkItem(context.TODO(), func(workCtx context.Context) (err error) {
_, err = db.ExecContext(workCtx, query)
return err
})
}
// Wait for all workers to finish.
databasePool.Wait()
}
- 2 回答
- 0 关注
- 229 浏览
添加回答
举报
