美文网首页unitycsharp
极简线程安全对象池

极简线程安全对象池

作者: 雨落随风 | 来源:发表于2018-12-23 03:01 被阅读0次

本来想在重构 Timer 时候的使用,但是为了保留链式编程风格,就还是没能把这个对象池用上。但写了半天,扔掉可惜了,写在这里呢,希望能对读者有啥启发最好了。

核心代码

using System;
using System.Collections.Concurrent;
public interface IPoolable
{
    /// <summary>
    /// 对象池 用于标记层别是否可被回收
    /// </summary>
    AllocateState AllocateState { get; set; }
}
public enum AllocateState
{
     InUse,//使用中
     Recycled //已回收
}

public sealed class ObjectPool<T> where T : IPoolable 
{
    internal ConcurrentStack<T> items; //线程安全 栈
    private Func<T> factory; //埋入的实例化 规则
    public int Count //池子有多少货
    {
        get
        {
            return items.Count;
        }
    }
    public int Capacity { get; set; } //池子有多大

    internal ObjectPool(Func<T> factory,int capacity = 100)
    {
        this.factory = factory;
        this.Capacity = capacity;
        items = new ConcurrentStack<T>();
    }
    public void Clear()
    {
        items.Clear();
    }
    public T Allocate() //分配
    {
        T item = default(T);
        if (items.IsEmpty || !items.TryPop(out item))
        {
            item =factory.Invoke();
        }
        item.AllocateState = AllocateState.InUse; //标记为使用中
        return item;
    }
    public void Release(T target) //释放
    {
        //池爆炸了再多都不再要了,当然,如果不是 InUse 的就更别想挤进来~
        if (target.AllocateState.Equals(AllocateState.InUse) && items.Count < Capacity) 
        {
            items.Push(target);
        }
    }
}

Tips:

  1. 使用了泛型 T 实现了类型安全;
  2. 使用了 ConcurrentStack 线程安全栈,微软底层帮处理了可能存在的并发问题 ;
  3. 控制反转 : Func<T> factory ,可以预先埋入实例化逻辑,
  4. 使用 IPoolable 接口标记可回收的对象

使用场景(伪代码)

public class A : IPoolable  //这个是可回收对象
{
    public AllocateState AllocateState{get;set;}
    public string feild;
    public void RestData() // 重置数据
    {
        feild = string.Empty;
    }
}

public class B  //这个类 演示了怎么使用这个 对象池
{
    public void Test()
    {
        ObjectPool<A> pool = new ObjectPool<A>(InstantiateRule); //造个池子,埋入实例化规则
        A a = pool.Allocate(); //分配对象
        a.feild = "假装在使用这个对象";
        a.RestData(); //重置数据准备回收啦
        pool.Release(a); //回收到对象池
    }
    private A InstantiateRule()//实例化规则
    {
        return new A(); //当然可以写更多定制化的东西在里面
    }
}

扩展阅读:

  1. GitHub/UnityCsReference/ObjectPool.cs (Unity官方公开的源码)
  2. System.Reflection.Internal.ObjectPool<T>
  3. C# 队列和栈 线程安全 - 天才卧龙 - 博客园
  4. Unity 游戏框架搭建 (二十) 更安全的对象池 - 凉鞋的笔记 - 博客园

相关文章

  • 极简线程安全对象池

    本来想在重构 Timer 时候的使用,但是为了保留链式编程风格,就还是没能把这个对象池用上。但写了半天,扔掉可惜了...

  • Java 基础

    1. 基础语法 2. 面向对象 3. 常用API、常用类型 4. 集合 5. 多线程(线程状态、线程安全、线程池、...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • 线程池(3)终止线程池原理

    终止线程池 一、终止线程池方法 1、 shutdown() 安全的终止线程池 2、 shutdownNow() 强...

  • 线程池学习笔记

    1、线程池的定义 2、Executors创建线程池的方式 3、ThreadPoolExecutor对象 4、线程池...

  • wait() notify() notifyAll()讲解

    1.锁池 等待池 每个对象都内置了锁池跟等待池。锁池: 某个线程拥有了该对象的锁,其他线程执行时,遇到该对象修饰的...

  • 线程池创建和相关知识

    线程池创建(单例):Android线程池得要这么用 - 简书 线程池相关知识:Android开发之线程池使用总结 ...

  • String,StringBuilder,Stringbuffe

    String :不可变,每次对String的操作都会在“常量池”中生成新的String对象,线程安全。 Strin...

  • 知识点、线程池、spring 代理机制、RPC、事务、负载均衡、

    1.什么叫线程池吗? 所谓的线程池指的就是一组线程对象被统一的一个外部对象包装(池对象),而后在这个池里面就可以利...

  • [JAVA][线程池]

    1.线程池理解 线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象传给线程池,线程池就会启动一...

网友评论

    本文标题:极简线程安全对象池

    本文链接:https://www.haomeiwen.com/subject/ccrgkqtx.html