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. 在WPF中绘制多维数据集

    原文 https://stuff.seans.com/2008/08/13/drawing-a-cube-in-wpf/ 是时候使用WPF绘制一个简单的3D对象了.作为WPF中3D图形的快速介绍,让我 ...

  2. 解决ArcMap绘图错误

    这几天在用ArcMap对shapefile做矢量化的过程中,遇到一件特别蛋疼的事,ArcMap竟然会出现绘图错误.如下所示: 纠结了许久之后,终于在Esri社区找到了解决办法:帮助文档中说 “检查属性 ...

  3. 阿里云Kubernetes服务上使用Tekton完成应用发布初体验

    Tekton 是一个功能强大且灵活的 Kubernetes 原生开源框架,用于创建持续集成和交付(CI/CD)系统.通过抽象底层实现细节,用户可以跨多云平台和本地系统进行构建.测试和部署. 本文是基于 ...

  4. Sublime插件:增强篇

    Sublime Text 如何安装插件详见:https://packagecontrol.io/installation WordCount:可以实时显示当前文件的字数. 安装后,后下角多出字数 En ...

  5. Duplicate keys detected: '0'. This may cause an update error.

    在运行vue项目的时候报了:[Vue warn]: Duplicate keys detected: ‘0’. This may cause an update error(错误,检测到重复的key值 ...

  6. clear简单的例子

    非常实用,非常简单的例子,结果都在图片里 <html> <head> <style> .keepbj { width:800px; height: 300px; b ...

  7. hadoop2.6.0 + hbase-1.0.0 伪分布配置

    1 基本配置 主机名: 192.168.145.154 hadoop2 ======= 2 etc/hadoop下文件配置 1)core-site.xml <configuration> ...

  8. 【原生JS】滑动门效果

    效果图: 思路:通过每次鼠标移动至目标上使所有图片重置为初始样式再向左移动目标及其左侧每个图片隐藏部分距离即实现. HTML: <!DOCTYPE html> <html> & ...

  9. 原生_H5交互插件(适用于与V2.1)

    这是js代码 /* * 适合版本为 2.1.0 * 前提是url上加 from=app */ var Native = {}; var ua = navigator.userAgent; var oU ...

  10. Vue中computed与method的区别

    转载于:https://segmentfault.com/a/1190000014478664?utm_source=tag-newest 1.computed区别于method的两个核心 在官方文档 ...