参考网上资料自己写的,可以运行,但是因为没找到类似的教程,只是自己想着写的,供大家参考,如果有错误,也请大家提出
主要逻辑就是一个聊天室房间,并发的向该房间增加、删除用户
package main
import (
"log"
"math/rand"
"os"
"os/signal"
"runtime"
"syscall"
)
type Room struct {
ch chan *User
users map[int]*User
userId int
running bool
}
type User struct {
userId int
action string
result bool
//该chan只用作阻塞ADD、DEL的routine
ch chan bool
}
func NewRoom() *Room {
room := &Room{
ch: make(chan *User, 200),
users: make(map[int]*User, 2000),
userId: 0,
running: true,
}
go room.beginListen()
return room
}
func (room *Room) beginListen() {
var user *User
var ok bool
for room.running {
user, ok = <-room.ch
if ok {
if user.action == "DEL" {
_, ok := room.users[user.userId]
if ok {
delete(room.users, user.userId)
user.result = true
log.Println("DEL, user num", len(room.users))
} else {
user.result = false
}
} else if user.action == "ADD" {
user.userId = room.userId
room.userId++
room.users[user.userId] = user
user.result = true
log.Println("ADD, user num", len(room.users))
}
//执行完成后,关闭user的ch,唤醒user的routine
close(user.ch)
} else {
log.Println("Exit Room routine")
break
}
}
}
func (room *Room) closeRoom() {
room.running = false
close(room.ch)
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
room := NewRoom()
for i := 0; i < 100; i++ {
go addUser(room)
go delUser(room)
}
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
log.Println("signal:", <-ch)
room.closeRoom()
}
//下面两个方法模拟多个线程并发操作
func addUser(room *Room) {
for {
user := &User{ch: make(chan bool), action: "ADD"}
room.ch <- user
//通过下面一句阻塞routine,等待room中执行ADD完成,通过关闭user的ch重新唤醒该routine
<-user.ch
log.Println("ADD user", user.result)
}
}
func delUser(room *Room) {
for {
user := &User{userId: rand.Intn(999), ch: make(chan bool), action: "DEL"}
room.ch <- user
//通过下面一句阻塞routine,等待room中执行DEL完成,通过关闭user的ch重新唤醒该routine
<-user.ch
log.Println("DEL user", user.result)
}
}