以下是使用 Go 语言重写的代码:
package main
import (
"fmt"
"sync"
)
type Task struct {
f func() error
}
type ThreadPool struct {
maxWorkers int
taskQueue chan Task
wg sync.WaitGroup
}
func NewThreadPool(maxWorkers int) *ThreadPool {
return &ThreadPool{
maxWorkers: maxWorkers,
taskQueue: make(chan Task),
}
}
func (tp *ThreadPool) Start() {
for i := 0; i < tp.maxWorkers; i++ {
go tp.worker()
}
}
func (tp *ThreadPool) Submit(f func() error) {
tp.wg.Add(1)
task := Task{f}
select {
case tp.taskQueue <- task:
// submitted successfully
default:
// queue is full, block until there's room
tp.taskQueue <- task
}
}
func (tp *ThreadPool) Shutdown() {
close(tp.taskQueue)
// wait for all workers to complete their tasks and exit gracefully
tp.wg.Wait()
}
func (tp *ThreadPool) worker() {
defer tp.wg.Done()
for task := range tp.taskQueue {
if err := task.f(); err != nil {
fmt.Printf("Error: %v\n", err)
break
}
}
}
在 NewThreadPool
函数中,我们创建了一个包含最大工作线程数和任务队列的结构体,并返回它。
在 Start
方法中,我们启动了指定数量的工作线程。每个工作线程都将从任务队列中取出任务并执行它们。
在 Submit
方法中,我们首先将任务包装成一个 Task
对象,并使用 sync.WaitGroup
来跟踪正在运行的任务数量。然后,我们尝试将任务放入队列中,如果队列已满,则会阻塞直到有空间可用为止。
在 Shutdown
方法中,我们关闭了任务队列,这会使所有工作线程停止处理新的任务并退出。然后,我们使用 WaitGroup
等待所有正在运行的任务完成并退出。
在 worker
方法中,我们从任务队列中获取任务并执行它们。如果执行过程中出现错误,则直接打印错误信息并退出整个池。
请注意,在 Go 中没有办法通过异常来终止函数的执行。相反,我们必须显式检查每个操作是否成功,并在失败时采取适当的措施。