今天又仔细看了下这篇blog,感觉博文下面的评论也蛮不错的,按照 Jesper Louis Andersen 的思路我重新写了一遍,附在下面,有啥问题欢迎指正。
PS 1:当然如果是队列实现,这篇文章的代码就基本足矣了
PS 2:这个Thread的第一封邮件少了“应用”,应该为“讲channel 和 Goroutine应用的一篇blog”
package main
import (
"fmt"
"time"
"rand"
)
type Call struct {
id int
duration int
start_time int64
end chan bool
}
func (c *Call) Wait() {
<-c.end
}
type Agent struct {
id int
cc *CallCenter
}
func (ag *Agent) Run(c *Call) {
fmt.Printf("Agent: %d, answering Call: %d\n", ag.id, c.id)
time.Sleep(int64(c.duration * 1000000))
fmt.Printf("Call %d answered; waited %d milliseconds\n", c.id, (time.Nanoseconds()-c.start_time)/1000000)
}
func (ag *Agent) Becomeidle(cc *CallCenter) {
cc.idleagents <- ag
}
type CallCenter struct {
allagents []Agent
idleagents chan *Agent
}
func (cc *CallCenter) Open(agentnum int) {
fmt.Println("Call center opening")
cc.allagents = make([]Agent, agentnum)
cc.idleagents = make(chan *Agent, agentnum)
for _, ag := range cc.allagents {
(&ag).Becomeidle(cc)
}
fmt.Println("Call center open")
}
func (cc *CallCenter) Close() {
fmt.Println("Call center closing")
close(cc.idleagents)
fmt.Println("Call center closed")
}
func handle(cc *CallCenter, c *Call) {
ag := <-cc.idleagents
ag.Run(c)
ag.Becomeidle(cc)
c.end <- true
}
func elapse(tip string, begin int64) {
end := time.Nanoseconds()
fmt.Printf("%s: %d seconds\n", tip, (end-begin)/1000000000)
}
func main() {
num_agents := 1
num_calls := 10
max_dur := 5
call_center := new(CallCenter)
defer elapse("All Time", time.Nanoseconds())
call_center.Open(num_agents)
allc := make([]*Call, num_calls)
for i := 0; i < num_calls; i++ {
allc[i] = &Call{i, rand.Int() * max_dur, time.Nanoseconds(), make(chan bool)}
}
for _, c := range allc {
go handle(call_center, c)
}
for _, c := range allc {
c.Wait()
}
call_center.Close()
}