实体池实现
来源:互联网 发布:ubuntu查看显卡使用率 编辑:程序博客网 时间:2024/06/05 09:50
实体池实现
引题
这里主要讲解不仅仅是实体池的实现,还有借鉴的编码规则,注视的格式,培养自己在以后的编码过程中养成好的习惯。
接口
池的设计,主要的就是取出和放回操作。每一个模块都需要有一定的自我
监控能力,可以反应自身的使用情况,因此真对实体池,我们提出实体总量和使用情况。接口具体如下:
// 实体池的接口类型。
type Pool interface {
Take() (Entity, error) // 取出实体
Return(entity Entity) error // 归还实体。
Total() uint32 // 实体池的容量。
Used() uint32 // 实体池中已被使用的实体的数量。
}
实现
在实现的过程中,需要计数实体总量,标志实体池的类型,因为要实现扩展性,我们需要外部提供一个函数作为实现实体的标准。还有容纳器包含实体,可以链表活着其他的,但是chan类型似乎更加的友好做为无状态链表操作。还有一个map用于标识实体是否正在用。当然作为并发组件,线程安全是必要的。
// 实体池的实现类型。type myPool struct { total uint32 // 池的总容量。 etype reflect.Type // 池中实体的类型。 genEntity func() Entity // 池中实体的生成函数。 container chan Entity // 实体容器。 idContainer map[uint32]bool // 实体ID的容器。 mutex sync.Mutex // 针对实体ID容器操作的互斥锁。
我们需要为每一个结构体提供NewXXX的函数,用于创建。注意这里创建的时候需要同时提供初始化整个实体池,这个池比较简单,是固定大小的,没有动态创建实体。灵活性不高,其实golang的包中提供了这种类似的池操作,大家可以看看源码如何实现。
// 创建实体池。func NewPool( total uint32, entityType reflect.Type, genEntity func() Entity) (Pool, error) { if total == 0 { errMsg := fmt.Sprintf("The pool can not be initialized! (total=%d)\n", total) return nil, errors.New(errMsg) } size := int(total) container := make(chan Entity, size) idContainer := make(map[uint32]bool) for i := 0; i < size; i++ { newEntity := genEntity() if entityType != reflect.TypeOf(newEntity) { errMsg := fmt.Sprintf("The type of result of function genEntity() is NOT %s!\n", entityType) return nil, errors.New(errMsg) } container <- newEntity idContainer[newEntity.Id()] = true } pool := &myPool{ total: total, etype: entityType, genEntity: genEntity, container: container, idContainer: idContainer, } return pool, nil}
下面直接给出整个接口函数的实现,不做一一讲解
func (pool *myPool) Take() (Entity, error) { entity, ok := <-pool.container if !ok { return nil, errors.New("The inner container is invalid!") } pool.mutex.Lock() defer pool.mutex.Unlock() pool.idContainer[entity.Id()] = false return entity, nil}func (pool *myPool) Return(entity Entity) error { if entity == nil { return errors.New("The returning entity is invalid!") } if pool.etype != reflect.TypeOf(entity) { errMsg := fmt.Sprintf("The type of returning entity is NOT %s!\n", pool.etype) return errors.New(errMsg) } entityId := entity.Id() casResult := pool.compareAndSetForIdContainer(entityId, false, true) if casResult == 1 { pool.container <- entity return nil } else if casResult == 0 { errMsg := fmt.Sprintf("The entity (id=%d) is already in the pool!\n", entityId) return errors.New(errMsg) } else { errMsg := fmt.Sprintf("The entity (id=%d) is illegal!\n", entityId) return errors.New(errMsg) }}// 比较并设置实体ID容器中与给定实体ID对应的键值对的元素值。// 结果值:// -1:表示键值对不存在。// 0:表示操作失败。// 1:表示操作成功。func (pool *myPool) compareAndSetForIdContainer( entityId uint32, oldValue bool, newValue bool) int8 { pool.mutex.Lock() defer pool.mutex.Unlock() v, ok := pool.idContainer[entityId] if !ok { return -1 } if v != oldValue { return 0 } pool.idContainer[entityId] = newValue return 1}func (pool *myPool) Total() uint32 { return pool.total}func (pool *myPool) Used() uint32 { return pool.total - uint32(len(pool.container))}
感悟
主要感悟在于编码的格式,在哪里写注释,在哪里定义,变量的命名格式都有了新的了解和学习。
- 实体池实现
- 实现 组件-实体-系统
- Hibernate 实现继承实体
- 实现 组件-实体-系统
- 一个实体类基类实现
- 实体添加扩展实现
- HTML5实现的实体时钟
- java实体类实现接口
- Hibernate高级实体关联映射之多值的实体关联(实体类实现三重关联)
- 实体
- 实体
- 实体
- 实体
- 实体
- JavaScript模拟实体类的实现
- 四、创建Model,实现业务实体
- 怎样用OpenNLP来实现命名实体识别
- 利用哈希表实现实体类索引
- Attempt to invoke virtual method void android.support.v7.widget.SearchView.setSearchableInfo(androi
- ArcGIS Editor for OSM, 10.2.x Desktop安装问题
- CentOS源码包安装apache、nginx服务
- nyoj 题目287 Radar 贪心算法
- View 基础知识 ----------------------------(1)
- 实体池实现
- 系统大小端的头文件定义
- android 连接wifi
- equals() & hashCode()
- Uva 6609
- 二、Activiti5 核心API
- redis集群环境安装(参照redis中文官网,中间遇到了一些问题,so,记录一下)
- 【NYOJ-71】 独木舟上的旅行
- CSU-ACM2017暑期训练6-bfs C