在 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 秒后才启动?

A​​kka 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
}