pekko/akka-actor/src/test/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala

115 lines
3.3 KiB
Scala

package se.scalablesolutions.akka.actor.dispatch
import org.scalatest.matchers.MustMatchers
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import java.util.concurrent.{TimeUnit, CountDownLatch}
import se.scalablesolutions.akka.actor.{IllegalActorStateException, Actor}
import Actor._
import se.scalablesolutions.akka.dispatch.{MessageQueue, Dispatchers}
object ExecutorBasedEventDrivenWorkStealingDispatcherSpec {
val delayableActorDispatcher = Dispatchers.newExecutorBasedEventDrivenWorkStealingDispatcher("pooled-dispatcher").build
val sharedActorDispatcher = Dispatchers.newExecutorBasedEventDrivenWorkStealingDispatcher("pooled-dispatcher").build
val parentActorDispatcher = Dispatchers.newExecutorBasedEventDrivenWorkStealingDispatcher("pooled-dispatcher").build
class DelayableActor(name: String, delay: Int, finishedCounter: CountDownLatch) extends Actor {
self.dispatcher = delayableActorDispatcher
@volatile var invocationCount = 0
self.id = name
def receive = {
case x: Int => {
Thread.sleep(delay)
invocationCount += 1
finishedCounter.countDown
}
}
}
class FirstActor extends Actor {
self.dispatcher = sharedActorDispatcher
def receive = {case _ => {}}
}
class SecondActor extends Actor {
self.dispatcher = sharedActorDispatcher
def receive = {case _ => {}}
}
class ParentActor extends Actor {
self.dispatcher = parentActorDispatcher
def receive = {case _ => {}}
}
class ChildActor extends ParentActor {
}
}
/**
* @author Jan Van Besien
*/
class ExecutorBasedEventDrivenWorkStealingDispatcherSpec extends JUnitSuite with MustMatchers {
import ExecutorBasedEventDrivenWorkStealingDispatcherSpec._
@Test def fastActorShouldStealWorkFromSlowActor {
val finishedCounter = new CountDownLatch(110)
val slow = actorOf(new DelayableActor("slow", 50, finishedCounter)).start
val fast = actorOf(new DelayableActor("fast", 10, finishedCounter)).start
var sentToFast = 0
for (i <- 1 to 100) {
// send most work to slow actor
if (i % 20 == 0) {
fast ! i
sentToFast += 1
}
else
slow ! i
}
// now send some messages to actors to keep the dispatcher dispatching messages
for (i <- 1 to 10) {
Thread.sleep(150)
if (i % 2 == 0) {
fast ! i
sentToFast += 1
}
else
slow ! i
}
finishedCounter.await(5, TimeUnit.SECONDS)
fast.mailbox.asInstanceOf[MessageQueue].isEmpty must be(true)
slow.mailbox.asInstanceOf[MessageQueue].isEmpty must be(true)
fast.actor.asInstanceOf[DelayableActor].invocationCount must be > sentToFast
fast.actor.asInstanceOf[DelayableActor].invocationCount must be >
(slow.actor.asInstanceOf[DelayableActor].invocationCount)
slow.stop
fast.stop
}
@Test def canNotUseActorsOfDifferentTypesInSameDispatcher(): Unit = {
val first = actorOf[FirstActor]
val second = actorOf[SecondActor]
first.start
intercept[IllegalActorStateException] {
second.start
}
}
@Test def canNotUseActorsOfDifferentSubTypesInSameDispatcher(): Unit = {
val parent = actorOf[ParentActor]
val child = actorOf[ChildActor]
parent.start
intercept[IllegalActorStateException] {
child.start
}
}
}