8、Akka任务调度(Dispatcher)

Dispatcher解析

Dispatcher是将如何执行任务与何时运行任务两者解耦,所 Actor或Future的工作都是由 (Executor或Dispatcher)分配的资源来完成的。一般来说,Dispatcher会包含一些线程, 这些线程会负责调度并运行任务, 比如处理 Actor 的消息以及线程中的Future事件。
在这里插入图片描述

不自己创建Dispatcher时使用的是默认Dispathcer,如果任务中有些耗时任务,容易将默认线程池打满,影响其他任务的调度。

Excutor

Dispatcher 基于 Executor,所以在具体介绍 Dispatcher 之前,我们将介绍两种主要的Executor类型:ForkJoinPoolThreadPool

  • ThreadPool Excutor: 有一个工作队列,队列中包含了分配给各队列的工作,线程空闲时就从队列中认领工作,允许线程重用,减少线程分配和销毁的开销。
  • ForkJoinPool Excutor::使用一种分治算法,递归地将任务分隔成更小的子任务,然后把子任务分配给不同的线程运行,最后将运行结果组合起来。

ForkJoinPool的Executor几乎总是比ThreadPool的Executor效率更高,是我们的默认选择

创建Dispatcher

  1. 在application.conf文件中定义一个Dispatcher。

    my-dispatcher {
      # Dispatcher的类型,选择符合场景的Dispatcher,这里使用的是默认类型Dispatcher
      type = Dispatcher
      # 定义Excutor类型,上面也介绍过两种Excutor
      executor = "fork-join-executor"
      fork-join-executor {
        # 单核最少线程数,Excutor中最少线程数=parallelism-min*parallelism-factor
        parallelism-min = 2
        # 此项最好配置成机器的CPU核数
        parallelism-factor = 8.0
        # 单核最多线程数,Excutor中最多线程数=parallelism-max*parallelism-factor
        parallelism-max = 1000
      }
      # 跳到另一个Acotr之前每个Actor最多处理消息数量,这个参数为了防止单个Acotr一直占用线程,设置此Acotr最多执行多少消息就要被调度
      throughput = 1000
    }
    
  2. 通过application.confg中配置好的Dispatcher创建Dispatcher对象

    system.actorOf(Props[MyActor].withDispatcher("my-pinned-dispatcher"))
    

在上面Type使用的是默认的Dispatcher,在Akka中有四种类型的 Dispatcher 可以用于描述如何在 Actor 之间共享线程:

Type特征
Dispatcher默认的 Dispatcher 类型。将会使用定义的 Executor,在 Actor 中处理消息。在大多数情况下,这种类型能够提供最好的性能。
PinnedDispatcher给 每 个 Actor 都分配自己独有的线程。 这种类型的 Dispatcher 为每个 Actor 都创建一个 ThreadPool Executor, 每个 Executor 中都包含一个线程。
如果希望确保每个 Actor 都能够立即响应,那么这似乎是个不错的方法。不过PinnedDispatcher 比其他共享资源的方法效率更高的情况其实并不多。可以在单个 Actor 必须处理很多重要工作的时候试试这种类型的 Dispatcher,否则的话不推荐使用。
CallingThreadDispatcher这个 Dispatcher 比较特殊,它没有 Executor,而是在发起调用的线程上执行工作。这种 Dispatcher 主要用于测试,特别是调试。由于发起调用的线程负责完成工作, 所以清楚地看到栈追踪信息, 了解所执行方法的完整上下文。这对于理解异常是非常有用的。每个 Actor 会获取一个锁,所以每次只有一个线程可以在 Actor 中执行代码,而如果多个线程向一个 Actor 发送信息的话, 就会导致除了拥有锁的线程之外的所有线程处于等待状态。 本书前面介绍过的 TestActorRef 就是基于 CallingThreadDispatcher 实现支持在测试中同步执行工作的。
BalancingDispatcherBalancingDispatcher 有一点很特殊:Pool 中的所有Actor 都共享同一个邮箱,并且会为 Pool 中的每个 Actor 都创建一个线程。使用 BalancingDispatcher 的 Actor 从邮箱中拉取消息,所以只要有 Actor 处于空闲状态,就不会有任何 Actor 的工作队列中存在任务。这是工作窃取的一个变种,所有 Actor 都会从一个共享的邮箱中拉取任务。两者在性能上的优点也类似。

参考文献

  • 《Akka入门与实践》

关注公众号回复Akka领取《Akka入门与实践》书籍

关注公众号 数据工匠记 ,专注于大数据领域离线、实时技术干货定期分享!个人网站 www.lllpan.top
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Akka Scheduler是Akka框架中的一个任务调度器,它可以用于执行基于时间的调度任务。Akka框架是一个用于构建高并发和分布式应用的工具包,它基于Actor模型,提供了可扩展、高可用、高吞吐量的分布式计算能力。 在Akka框架中,Scheduler是一个全局的调度器,它负责执行所有的任务调度。Scheduler的使用非常简单,只需要调用ActorSystem.scheduler().schedule()方法即可创建一个新的任务调度Akka Scheduler支持两种类型的任务调度:一次性任务和重复任务。一次性任务只会执行一次,而重复任务会按照指定的时间间隔重复执行。调度时间可以使用Duration类型来定义,Duration类型可以表示时间间隔,例如1秒、2分钟等。 下面是一个使用Akka Scheduler创建任务调度的示例代码: ```java import akka.actor.ActorSystem; import scala.concurrent.duration.Duration; import java.util.concurrent.TimeUnit; public class SchedulerDemo { public static void main(String[] args) { ActorSystem system = ActorSystem.create("MyActorSystem"); // 创建一个一次性任务 system.scheduler().scheduleOnce(Duration.create(1, TimeUnit.SECONDS), new Runnable() { @Override public void run() { System.out.println("One time task executed."); } }, system.dispatcher()); // 创建一个重复任务 system.scheduler().schedule(Duration.Zero(), Duration.create(1, TimeUnit.SECONDS), new Runnable() { @Override public void run() { System.out.println("Recurring task executed."); } }, system.dispatcher()); } } ``` 在上面的示例中,我们创建了一个一次性任务和一个重复任务,它们分别在1秒后执行和每隔1秒执行一次。在实际开发中,我们可以使用Akka Scheduler来执行定时任务、清理任务、统计任务等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值