• 用Golang写一个简单的eventBus(Pub/Sub)


    编写一个简单的EventBus

    先放github地址
    用go写一个Pub/Sub比Java简单多了,因为go有chan这机制。

    总线(Bus)

    管理所有专题(topic)和订阅该专题的用户。以map形式存储。

    这里加一把表级锁。

    type Bus struct {
    	subNode map[string]*node
    	rw      sync.RWMutex
    }
    

    节点(node)

    node内管理着订阅同一专题的用户序列。
    这里加了一把序列锁,在Bus的表级锁被举起时,node的锁不会使用,这样能减小锁粒度,提高并发度。

    // node contains a slice of subs that subscribe same topic
    type node struct {
    	subs []Sub
    	// Note node's rw will not be used when bus's rw is helded.
    	rw sync.RWMutex
    }
    

    用户(Sub)

    Sub内有一个chan成员变量,每次有消息被发送到chan内时,由于chan的机制,Sub就能及时收到被推送的消息。

    type Sub struct {
    	out chan interface{}
    }
    

    订阅

    把sub添加到bus中map便利的topic对应的序列中。
    注意这里用到了两种锁的上锁解锁时机。

    func (b *Bus) Subscribe(topic string, sub Sub) {
    	b.rw.Lock()
    	if n, ok := b.subNode[topic]; ok {
    		// found the node
    		b.rw.Unlock()
    		n.rw.Lock()
    		defer n.rw.Unlock()
    		n.subs = append(n.subs, sub)
    	} else {
    		defer b.rw.Unlock()
    		n := NewNode()
    		b.subNode[topic] = &n
    	}
    }
    

    发布

    逻辑就是遍历用户序列,把消息发送到sub的chan中

    func (b *Bus) Publish(topic string, msg interface{}) error {
    	b.rw.Lock()
    	if n, ok := b.subNode[topic]; ok {
    		// found the node
    		b.rw.Unlock()
    		n.rw.RLock()
    		defer n.rw.RUnlock()
    		// got the subs list and publish msg
    		go func(subs []Sub, msg interface{}) {
    			for _, sub := range subs {
    				sub.receive(msg)
    			}
    		}(n.subs, msg)
    		// successed return null
    		return nil
    	} else {
    		// topic not exist
    		return errors.New("topic not exist")
    	}
    
    }
    

    使用

    见仓库内的test文件

  • 相关阅读:
    练习四十:数组逆向输出
    练习三十九:数组插入排序
    Java awt组件间的继承关系
    java ArrayList
    java Scanner中的hasNext()方法
    java中String对象的存储位置
    java初始化块执行顺序
    java二维数组
    java数组变量
    Java数组初始
  • 原文地址:https://www.cnblogs.com/Jun10ng/p/13173368.html
Copyright © 2020-2023  润新知