Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Akka如何从ForkJoinPool中获益?_Java_Multithreading_Akka_Threadpool_Forkjoinpool - Fatal编程技术网

Java Akka如何从ForkJoinPool中获益?

Java Akka如何从ForkJoinPool中获益?,java,multithreading,akka,threadpool,forkjoinpool,Java,Multithreading,Akka,Threadpool,Forkjoinpool,声明默认dispatcher是一个fork-join-executor,因为它“在大多数情况下提供优异的性能”。 我想知道为什么会这样 从 ForkJoinPool与其他类型的ExecutorService的区别主要在于采用了工作窃取:池中的所有线程都试图查找并执行提交给池和/或由其他活动任务创建的任务(如果不存在,则最终阻止等待工作)。当大多数任务产生其他子任务时(大多数ForkJoinTasks也是如此),以及当许多小任务从外部客户端提交到池中时,(1)这可以实现高效处理。尤其是在构造函数中

声明默认dispatcher是一个
fork-join-executor
,因为它“在大多数情况下提供优异的性能”。
我想知道为什么会这样

ForkJoinPool与其他类型的ExecutorService的区别主要在于采用了工作窃取:池中的所有线程都试图查找并执行提交给池和/或由其他活动任务创建的任务(如果不存在,则最终阻止等待工作)。当大多数任务产生其他子任务时(大多数ForkJoinTasks也是如此),以及当许多小任务从外部客户端提交到池中时,(1)这可以实现高效处理。尤其是在构造函数中将asyncMode设置为true时,ForkJoinPool也可能适合用于从未加入的事件样式任务。

首先,我想Akka不是案例(1)的一个例子,因为我不知道Akka是如何分叉任务的,我的意思是,在许多任务中分叉的任务是什么?
我将每条消息视为一个独立的任务,这就是为什么我认为Akka类似于案例(2),其中消息是许多小任务(通过!和?)提交到
ForkJoinPool

下一个问题,虽然与akka没有严格的关系,但将是,为什么fork和join(允许盗用工作的
ForkJoinPool
的主要功能)没有被使用的用例仍然可以从ForkJoinPool中受益?

我们注意到上下文切换的数量异常,超过每秒70000个。
这一定是问题所在,但是什么原因造成的呢?Viktor提出了一个有保留的猜测,即它必须是线程池执行器的任务队列,因为这是共享的,并且LinkedBlockingQueue中的锁可能在存在争用时生成上下文切换

但是,如果Akka确实没有使用
ForkJoinTasks
,则外部客户端提交的所有任务都将在共享队列中排队,因此争用应该与
ThreadPoolExecutor
中的争用相同

因此,我的问题是:

  • Akka使用
    ForkJoinTasks
    (案例(1))或与案例(2)相关
  • 为什么
    ForkJoinPool
    在案例(2)中是有益的,如果外部客户端提交的所有任务都将推送到共享队列,并且不会发生工作窃取
  • 什么是“从未加入的事件样式任务”(案例3)的示例

  • 更新 正确答案是来自约翰南德伦的,不过我想补充一些亮点

    • Akka没有使用fork和join功能,因为AFAIK与Actor模型,或者至少我们是如何实现它的,没有真正的用例(来自johanandren的评论)。
      因此,我认为Akka不是案例(1)的一个例子是正确的
    • 在我最初的回答中,我说外部客户端提交的所有任务都将在共享队列中排队。
      这是正确的,但仅适用于FJP的早期版本(jdk7)。 在jdk8中,提交队列被许多“提交队列”所取代。 很好地解释了这一点: 现在,在(IIRC)JDK 7u12之前,ForkJoinPool有一个全局提交队列。当工作线程耗尽本地任务以及要窃取的任务时,他们到达那里并尝试查看外部工作是否可用。在这种设计中,与由ArrayBlockingQueue支持的常规ThreadPoolExecutor相比,没有任何优势。[…]
      现在,外部提交进入其中一个提交队列。然后,没有工作可供咀嚼的工作人员可以首先查看与特定工作人员关联的提交队列,然后四处查看其他工作人员的提交队列。人们也可以称之为“偷工减料”

    因此,这在不使用fork-join的场景中启用了工作窃取。作为

    当大量客户端提交大量任务时,吞吐量显著提高。(我在微型基准上测量了高达60倍的加速比)。其想法是以与工人类似的方式对待外部提交者——使用随机排队和偷窃。(这需要一个大的内部重构来解除工作队列和工作人员的关联。)当所有任务都是异步的并提交到池而不是分叉时,这也大大提高了吞吐量,这成为构造参与者框架以及许多您可能使用ThreadPoolExecutor的普通服务的合理方式

    • 关于FJP,还有另一个值得一提的奇点 4%对FJP来说确实不算多。您仍然需要对FJP进行权衡 需要注意的是:FJP会让线程旋转一段时间 能够更快地处理准时到达的工作。这确保了良好的延迟 在许多情况下。特别是如果您的池配置过多,那么 折衷的办法是在几乎空闲的情况下增加一点延迟,以避免更多的功耗 情况。


    Akka中的FJP是以
    asyncMode=true运行的
    因此第一个问题是-让外部客户端提交短/小异步工作负载。每个提交的工作负载都会分派一个参与者来处理其收件箱中的一条或几条消息,但它也用于执行Scala
    未来的
    操作

    当一个非
    ForkJoinTask
    计划在FJP上运行时,它将适应FJP并像
    ForkJoinTask
    s一样排队。没有一个提交任务是排队的(早期版本中可能有,JDK7),有很多提交任务是为了避免争用,如果队列为空,空闲线程可以从其他队列中拾取(窃取)任务

    请注意,默认情况下,我们当前运行的是Java8FJP的分叉版本,因为我们看到Java9FJP的吞吐量显著降低(它包含了相当多的更改)。这是