-
Notifications
You must be signed in to change notification settings - Fork 75
/
concurrency-design-airport-securitycheck-3.go
107 lines (92 loc) · 2.38 KB
/
concurrency-design-airport-securitycheck-3.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import "time"
const (
idCheckTmCost = 60
bodyCheckTmCost = 120
xRayCheckTmCost = 180
)
func idCheck(id string) int {
time.Sleep(time.Millisecond * time.Duration(idCheckTmCost))
print("\tgoroutine-", id, "-idCheck: idCheck ok\n")
return idCheckTmCost
}
func bodyCheck(id string) int {
time.Sleep(time.Millisecond * time.Duration(bodyCheckTmCost))
print("\tgoroutine-", id, "-bodyCheck: bodyCheck ok\n")
return bodyCheckTmCost
}
func xRayCheck(id string) int {
time.Sleep(time.Millisecond * time.Duration(xRayCheckTmCost))
print("\tgoroutine-", id, "-xRayCheck: xRayCheck ok\n")
return xRayCheckTmCost
}
func start(id string, f func(string) int, next chan<- struct{}) (chan<- struct{}, chan<- struct{}, <-chan int) {
queue := make(chan struct{}, 10)
quit := make(chan struct{})
result := make(chan int)
go func() {
total := 0
for {
select {
case <-quit:
result <- total
return
case v := <-queue:
total += f(id)
if next != nil {
next <- v
}
}
}
}()
return queue, quit, result
}
func newAirportSecurityCheckChannel(id string, queue <-chan struct{}) {
go func(id string) {
print("goroutine-", id, ": airportSecurityCheckChannel is ready...\n")
// start xRayCheck routine
queue3, quit3, result3 := start(id, xRayCheck, nil)
// start bodyCheck routine
queue2, quit2, result2 := start(id, bodyCheck, queue3)
// start idCheck routine
queue1, quit1, result1 := start(id, idCheck, queue2)
for {
select {
case v, ok := <-queue:
if !ok {
close(quit1)
close(quit2)
close(quit3)
total := max(<-result1, <-result2, <-result3)
print("goroutine-", id, ": airportSecurityCheckChannel time cost:", total, "\n")
print("goroutine-", id, ": airportSecurityCheckChannel closed\n")
return
}
queue1 <- v
}
}
}(id)
}
func max(args ...int) int {
n := 0
for _, v := range args {
if v > n {
n = v
}
}
return n
}
func main() {
passengers := 30
queue := make(chan struct{}, 30)
newAirportSecurityCheckChannel("channel1", queue)
newAirportSecurityCheckChannel("channel2", queue)
newAirportSecurityCheckChannel("channel3", queue)
time.Sleep(5 * time.Second) // 保证上述三个goroutine都已经处于ready状态
for i := 0; i < passengers; i++ {
queue <- struct{}{}
}
time.Sleep(5 * time.Second)
close(queue) // 为了打印各通道的处理时长
time.Sleep(1000 * time.Second)
}