EventNext.net core下的一个事件驱动的应用框架,通过它代理创建的接口行为都是通过事件驱动的模式进行调用.由于EventNext的所有调用都是基于事件队列来进行,所以在资源控制上非常方便;它可以进行多样性的线程分配,其中Actor应用就是它的一种基础实现;在新的版中EventNext增加了一个新的特性就是线程容器,通过线程容器可以让N个类的行为在指定线程资源下运行。接来详细分析这个功能的应用。

线程容器的便利性

平时在多线程应用的时候一般都用线程池或自己定义线程处理,但这些都需要手动去处理和调用。实际有些情况是希望不同实例的所有方法运行在指定线程资源下,但又不想入侵式修改代码,这样处理起来就比较复杂了。但EventNext新版本的线程容器就能解决这种事情,它可以创建一个线程容器并指定那些对象的所有方法都在这个容器里执行,而容器的线程则可以根据实际情况来指定,这种完全透明的线程控制使用起来就非常方便(不过这版本的Actor暂不支持在线程容器中创建)。

接口定义准则

EventNext的所有任务都在由队列接管,但它实现的队列和平常的队列有所不同;EventNext的事件驱动队要求所有任务都用异步描述,它的特点是由上一个任务的完成来驱动下一下任务,不像同步处理队列在处理异步的时候不得不做线程等待。为了达到异步任务的要求接口的所有方法必须定义Task作为返回值(暂不支持属性处理)。

创建线程容器

组件提供一个EventNext.GetThreadContainer方法来获取一个线程容器,方法有两个参数,一个是容器的名称和对应容器的线程数量;当容器被创建后内部的线程数量不变,具体代码如下:

 var tc = EventCenter.GetThreadContainer("t1");

以上是获取一个名称为t1的线程容器,在不指定线程数的情况下为一个线程处理。接下来就可以通过容器创建相应的接口实例:

 var account = tc.Create<IAccount>();

以上是创建一个IAccount的实例,这个实例不管在多少个线程下调用最终都由t1这个线程容器去执行处理;每个容器可以创建多个接实例。

IAcouunt的实现

    [Service(typeof(IAccount))]
public class AccountImpl : IAccount
{ static AccountImpl()
{
Redis.Default.Host.AddWriteHost("192.168.2.19");
} public async Task Income(string name, int value)
{
await Redis.Default.Incrby(name, value);
} public async Task<string> Value(string name)
{
return await Redis.Default.Get<string>(name);
}
}

以上是针对一个Redis操作的实现,主要存在IO操作更容易测试到容器在不同线程下的差异。

测试代码

为了测试容器的效果,使用了不同的方式进行测试,分别是:不用线程容器和使用不同线程数的容器,测试代码如下:

  • 非线程容器

        static async Task None(int count)
{
var account = EventCenter.Create<IAccount>();
List<Task> tasks = new List<Task>();
var now = BeetleX.TimeWatch.GetElapsedMilliseconds();
for(int i=;i<;i++)
{
var t = Task.Run( async ()=> {
for (int k = ; k < count; k++)
await account.Income("ken",k);
});
tasks.Add(t);
}
await Task.WhenAll(tasks);
var value = await account.Value("ken");
Console.WriteLine($"none use time:{BeetleX.TimeWatch.GetElapsedMilliseconds()-now} ms");
}
  • 线程容器

        static async Task Threads(int threads, int count)
{
var tc = EventCenter.GetThreadContainer($"t{threads}",threads);
var account = tc.Create<IAccount>();
List<Task> tasks = new List<Task>();
var now = BeetleX.TimeWatch.GetElapsedMilliseconds();
for (int i = ; i < ; i++)
{
var t = Task.Run(async () => {
for (int k = ; k < count; k++)
await account.Income("ken", k);
});
tasks.Add(t);
}
await Task.WhenAll(tasks);
var value = await account.Value("ken");
Console.WriteLine($"{threads} thread use time:{BeetleX.TimeWatch.GetElapsedMilliseconds() - now} ms");
}

运行代码

        static async void Test()
{
Console.WriteLine("Warm-Up...");
await None();
await Threads(, );
await Threads(, );
await Threads(, );
for (int i = ; i < ; i++)
{
Console.WriteLine("Test...");
await None();
await Threads(, );
await Threads(, );
await Threads(, );
}
}

测试结果

Test...
none use time:1231 ms
1 thread use time:3479 ms
2 thread use time:2025 ms
4 thread use time:1208 ms
Test...
none use time:1246 ms
1 thread use time:3358 ms
2 thread use time:2025 ms
4 thread use time:1179 ms
Test...
none use time:1344 ms
1 thread use time:3385 ms
2 thread use time:1954 ms
4 thread use time:1187 ms
Test...
none use time:1210 ms
1 thread use time:3338 ms
2 thread use time:1933 ms
4 thread use time:1181 ms

默认情况下组件会针对请调用进行一个线程分配,这个分配机制依据队列的负载情况进行分配调用;线程容器则会根据当前容器的线程数来进行一个平均分配处理,从测试结果可以看到不同线程数下完成所需要的时间。

示例代码

https://github.com/IKende/BeetleX-Samples

事件驱动框架EventNext之线程容器的更多相关文章

  1. 【Java 并发】Executor框架机制与线程池配置使用

    [Java 并发]Executor框架机制与线程池配置使用 一,Executor框架Executor框架便是Java 5中引入的,其内部使用了线程池机制,在java.util.cocurrent 包下 ...

  2. 【Nginx】事件驱动框架和异步处理

    Nginx对请求的处理是通过事件触发的,模块作为事件消费者,仅仅能被事件收集.分发器调用.这与传统的Webserver是不同的. 传统的Webserver下,一个请求由一个进程消费.请求在建立连接后将 ...

  3. 从yii2框架中的di容器源码中了解反射的作用

    反射简介 参考官方简介的话,PHP 5 具有完整的反射 API,添加了对类.接口.函数.方法和扩展进行反向工程的能力. 此外,反射 API 提供了方法来取出函数.类和方法中的文档注释. YII2框架中 ...

  4. YII框架的依赖注入容器

    依赖注入(Dependency Injection,DI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象. 所谓的依赖就是,一个对象,要使用另外一个对象才能完成某些功能.那么这个对象就 ...

  5. 【Redis】事件驱动框架源码分析

    aeEventLoop初始化 在server.c文件的initServer函数中,对aeEventLoop进行了初始化: 调用aeCreateEventLoop函数创建aeEventLoop结构体,对 ...

  6. 【Redis】事件驱动框架源码分析(单线程)

    aeEventLoop初始化 在server.c文件的initServer函数中,对aeEventLoop进行了初始化: 调用aeCreateEventLoop函数创建aeEventLoop结构体,对 ...

  7. 服务框架HSF分析之一容器启动

    大家平时都在用这个服务框架.简单阅读了下代码,了解其原理可以方便解决一些常见hsf的问题.限于篇幅,整个分析将分几个系列发布.第一篇将简单介绍Hsf的启动和各组件之间关系. 一.  Hsf总体架构 这 ...

  8. [ASP.NET Core 3框架揭秘] 异步线程无法使用IServiceProvider?

    标题反映的是上周五一个同事咨询我的问题,我觉得这是一个很好的问题.这个问题有助于我们深入理解依赖注入框架在ASP.NET Core中的应用,以及服务实例的生命周期. 一.问题重现 我们通过一个简单的实 ...

  9. Minor【 PHP框架】4.服务容器与服务提供者

    框架Github地址:github.com/Orlion/Minor (如果觉得还不错给个star哦(^-^)V) 框架作者: Orlion 知乎:https://www.zhihu.com/peop ...

随机推荐

  1. P2P需集齐四大证照

    今后做P2P需集齐四大证照 比牌照制还严 2016-09-05 11:53:24 分类:热点观察 作者:汪祖刚 8月24日,P2P网贷监管细则在千呼万唤中始出来,整个行业内外的关注热度可谓史无前例.有 ...

  2. Oracle中组合索引的使用详解(转)

    在Oracle中可以创建组合索引,即同时包含两个或两个以上列的索引.在组合索引的使用方面,Oracle有以下特点: 1. 当使用基于规则的优化器(RBO)时,只有当组合索引的前导列出现在SQL语句的w ...

  3. sublime 插件安装packagecontrol

    https://packagecontrol.io/installation 第一步: Installation Simple The simplest method of installation ...

  4. H3C 分组交换连接模型

  5. 神经网络入门——8XOR感知器

    XOR 感知器     XOR 感知器就是一个这样的逻辑门:输入相同返回 0 ,输入不同返回 1.与之前的感知器不同,这里并不是线性可分的.要处理这类较为复杂的问题,我们需要把感知器连接起来. 我们用 ...

  6. 使用openssl 工具进行双向认证测试

    1,双向认证测试(需要根证书,客户证书,服务器证书以及各自的私钥)(验证通信双方的身份) openssl s_server -accept -key certs/server.key -cert ce ...

  7. H3C 会话层、表示层和应用层

  8. 反思K-S指标(KPMG大数据挖掘)

    评估信用评级模型,反思K-S指标 2015-12-05 KPMG大数据团队 KPMG大数据挖掘 “信用评级”的概念听起来可以十分直截了当.比如一天早上你接到电话,有个熟人跟你借钱,而你将在半睡半醒间迅 ...

  9. HDU 1286

    欧拉函数 φ函数的值 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数.φ(1)=1 ...

  10. JavaScript:4个常见的内存泄露

    什么是内存泄漏 内存泄漏基本上就是不再被应用需要的内存,由于某种原因,没有被归还给操作系统或者进入可用内存池. 编程语言喜欢不同的管理内存方式.然而,一段确定的内存是否被使用是一个不可判断的问题.换句 ...