在 akka.net 内立即触发多个线程
Fire multiple threads instantly in akka.net
我不确定这是否更多地与 akka.net 或 TPL 相关,但我将以演员为例来阐明问题。
问题简而言之:有什么方法可以让 akka.net 一次触发比我实际拥有的 CPU 个内核更多的线程? 这是示例代码和详细信息:
我目前使用的是配备 8 核处理器的笔记本电脑。假设我要创建 20 个演员:
for (int i = 0; i < 20; i++)
{
actorList.Add(system.ActorOf<ExampleActor>());
}
然后我要向所有这些人传递一条消息:
actorList[0].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 1\t" + DateTime.Now.TimeOfDay);
actorList[1].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 2\t" + DateTime.Now.TimeOfDay);
...
actorList[19].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 20\t" + DateTime.Now.TimeOfDay);
演员所做的一切,在接收消息时是以下伪造的 long-运行ning 过程:
Console.WriteLine("Accessing slow service\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000);
Console.WriteLine("Service call was successful\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
我在它的构造函数中也有这段代码,所以我知道actor是什么时候真正创建的:
public ExampleActor()
{
Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay);
....
}
所以现在当我 运行 应用程序时,我首先得到所有 20 个演员的 "sent message to actor" 行 - 在同一毫秒内。但是之后,当时间到了初始化的时候,发生的事情是一开始只创建了8个actors。
然后,由于 none 的其他演员已经完成了工作,恰好 1 秒后,另一个演员被初始化(第 9 个)。一秒钟后,我们创建了第 10 个演员并开始 Thread.Sleep 操作。
现在的问题是,有什么方法可以告诉 akka.net(或它下面的 TPL)我确定线程会为每个服务调用等待约 60 秒?这样所有 20 个线程都被一次触发,而不是一次启动 8 个,并且完整的 20 个线程 运行 仅在 12 秒后才启动?
Akka actors 运行 默认在 .Net ThreadPool 上。
您正在经历 ThreadPool 饥饿,所有可用线程都忙(每个 CPU 一个)。当它的所有线程都忙时,ThreadPool 每秒向其池中添加一个线程。
对于 "solve" 您的问题,您可以使用 ThreadPool.SetMinThreads 增加最小线程数。但真正的解决方法是不阻塞线程(而不是阻塞 actor)。
如果您的工作量受到 CPU 的限制,那么并发 运行 更多的 actors 并不会更快。
如果您的工作负载受 IO 限制,您应该异步调用它:
Receive<string>(msg =>
{
DoSomethingAsync(msg).PipeTo(Self);
}
Receive<Result>(msg =>
{
// Process the result
}
我不确定这是否更多地与 akka.net 或 TPL 相关,但我将以演员为例来阐明问题。
问题简而言之:有什么方法可以让 akka.net 一次触发比我实际拥有的 CPU 个内核更多的线程? 这是示例代码和详细信息:
我目前使用的是配备 8 核处理器的笔记本电脑。假设我要创建 20 个演员:
for (int i = 0; i < 20; i++)
{
actorList.Add(system.ActorOf<ExampleActor>());
}
然后我要向所有这些人传递一条消息:
actorList[0].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 1\t" + DateTime.Now.TimeOfDay);
actorList[1].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 2\t" + DateTime.Now.TimeOfDay);
...
actorList[19].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 20\t" + DateTime.Now.TimeOfDay);
演员所做的一切,在接收消息时是以下伪造的 long-运行ning 过程:
Console.WriteLine("Accessing slow service\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000);
Console.WriteLine("Service call was successful\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
我在它的构造函数中也有这段代码,所以我知道actor是什么时候真正创建的:
public ExampleActor()
{
Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay);
....
}
所以现在当我 运行 应用程序时,我首先得到所有 20 个演员的 "sent message to actor" 行 - 在同一毫秒内。但是之后,当时间到了初始化的时候,发生的事情是一开始只创建了8个actors。
然后,由于 none 的其他演员已经完成了工作,恰好 1 秒后,另一个演员被初始化(第 9 个)。一秒钟后,我们创建了第 10 个演员并开始 Thread.Sleep 操作。
现在的问题是,有什么方法可以告诉 akka.net(或它下面的 TPL)我确定线程会为每个服务调用等待约 60 秒?这样所有 20 个线程都被一次触发,而不是一次启动 8 个,并且完整的 20 个线程 运行 仅在 12 秒后才启动?
Akka actors 运行 默认在 .Net ThreadPool 上。
您正在经历 ThreadPool 饥饿,所有可用线程都忙(每个 CPU 一个)。当它的所有线程都忙时,ThreadPool 每秒向其池中添加一个线程。
对于 "solve" 您的问题,您可以使用 ThreadPool.SetMinThreads 增加最小线程数。但真正的解决方法是不阻塞线程(而不是阻塞 actor)。
如果您的工作量受到 CPU 的限制,那么并发 运行 更多的 actors 并不会更快。
如果您的工作负载受 IO 限制,您应该异步调用它:
Receive<string>(msg =>
{
DoSomethingAsync(msg).PipeTo(Self);
}
Receive<Result>(msg =>
{
// Process the result
}