goroutine的一种使用方法

参考网上资料自己写的,可以运行,但是因为没找到类似的教程,只是自己想着写的,供大家参考,如果有错误,也请大家提出

主要逻辑就是一个聊天室房间,并发的向该房间增加、删除用户

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)
	}
}



你可能感兴趣的:(golang)