Scala调度器工作者-参与者模式
我正在尝试使用标准的Scala.actors包为Scala设计一个dispatcher-worker-actor模式 dispatcher从Scala调度器工作者-参与者模式,scala,actor,dispatcher,Scala,Actor,Dispatcher,我正在尝试使用标准的Scala.actors包为Scala设计一个dispatcher-worker-actor模式 dispatcher从java.util.concurrent.LinkedBlockingQueue接收工作,并将其发送给工作者参与者进行处理。当所有工作完成后,调度员应该告诉每个工人退出,然后也应该退出。下面是我提出的代码,但当所有工作都完成时它会挂起(我认为dispatcher队列中有挂起的'GiveMeWork消息): import java.util.concurren
java.util.concurrent.LinkedBlockingQueue
接收工作,并将其发送给工作者参与者进行处理。当所有工作完成后,调度员应该告诉每个工人退出,然后也应该退出。下面是我提出的代码,但当所有工作都完成时它会挂起(我认为dispatcher队列中有挂起的'GiveMeWork
消息):
import java.util.concurrent.LinkedBlockingQueue
导入scala.actors.Actor
对象调度器
扩展演员{
println(“已创建的调度程序”)
def法案(){
val workers=(1到4).map(id=>(新Worker(id)).start()
环路{
反应{
案例'GiveMeWork=>
//println(“要求工作的工人”)
val(时间,i)=工作队列。take()
如果(时间==0){
println(“退出时间”)
工人。每小时(!?0升)
}否则{
println(“到达调度员:i:+i+”调度时间:+
时间+”,经过:“+(System.nanoTime()-time))
发送者!时间到了
}
案例'Quit=>
println(“被告知退出”)
寄件人下班
退出()
}
}
}
}
类工作者(id:Int)
扩展演员{
println(“创建的工人(“+id+”))
变量作业=0
def法案(){
调度员给了我工作
环路{
反应{
案例时间:长=>
如果(时间==0){
println(“工人(“+id+”)完成“+jobs+”jobs”)
寄件人下班
退出()
}否则{
println(“到达工作区(“+id+”):调度时间:+
时间+”,经过:“+(System.nanoTime()-time))
线程睡眠(id)
职位+=1
调度员给了我工作
}
}
}
}
}
val workQueue=newlinkedblockingqueue[(长,Int)](1000)
Dispatcher.start()
对于(i有一场比赛:
val (time, i) = workQueue.take()
所有工作都已完成,包括workQueue.put((0L,0))
,因此它将永远等待
同时使用不同类型的并发是个坏主意
调度员可以将任务限制通知任务源:
import scala.actors.{Actor, OutputChannel}
import scala.collection.mutable.Queue
case class Task(time: Long, i: Int)
case object GiveMeWork
case object Quit
case object OffDuty
object Dispatcher extends Actor {
println("Dispatcher created")
def act() {
val workers = (1 to 4).map(id => (new Worker(id)).start())
val waitingWorkers = Queue[OutputChannel[Any]](workers: _*)
val tasks = Queue[Task]()
var workSender: Option[OutputChannel[Any]] = None
loop {
react {
case GiveMeWork =>
if (!tasks.isEmpty) sender ! tasks.dequeue()
else waitingWorkers enqueue sender
workSender map { _ ! GiveMeWork }
workSender = None
case t: Task =>
if (!waitingWorkers.isEmpty) waitingWorkers.dequeue() ! t
else tasks enqueue t
if (tasks.length < 1000) sender ! GiveMeWork
else workSender = Some(sender)
case Quit =>
println("Told to quit")
workers.foreach{ _ ! Quit }
sender ! OffDuty
exit()
}
}
}
}
class Worker(id: Int)
extends Actor {
var jobs = 0
def act() {
loop {
react {
case t: Task =>
Thread.sleep(id)
jobs += 1
Dispatcher ! GiveMeWork
case Quit =>
println("Worker(" + id + ") completed " + jobs + " jobs")
sender ! OffDuty
exit()
}
}
}
}
Dispatcher.start()
for (i <- 0 until 5000) {
Thread.sleep(1)
Dispatcher !? Task(System.nanoTime(), i)
}
println("Telling Dispatcher to quit")
Dispatcher !? Quit
import scala.actors.{Actor,OutputChannel}
导入scala.collection.mutable.Queue
案例类任务(时间:长,i:Int)
案例对象给我的工作
案例对象退出
案件对象下班
对象调度器扩展了Actor{
println(“已创建的调度程序”)
def法案(){
val workers=(1到4).map(id=>(新Worker(id)).start()
val waitingWorkers=队列[OutputChannel[Any]](工作人员:*)
val tasks=队列[任务]()
var workSender:选项[OutputChannel[Any]]=None
环路{
反应{
case GiveMeWork=>
如果(!tasks.isEmpty)发件人!tasks.dequeue()
else waitingWorkers排队发送程序
工作区映射{{uu!GiveMeWork}
工作区=无
案例t:Task=>
如果(!waitingWorkers.isEmpty)waitingWorkers.dequeue()!t
其他任务排队
如果(tasks.length<1000)发送者!给我工作
else workSender=Some(发送方)
案例退出=>
println(“被告知退出”)
工人们,请退出
发送者!下班
退出()
}
}
}
}
类工作者(id:Int)
扩展演员{
变量作业=0
def法案(){
环路{
反应{
案例t:Task=>
线程睡眠(id)
职位+=1
调度员!给我工作
案例退出=>
println(“工人(“+id+”)完成“+jobs+”jobs”)
发送者!下班
退出()
}
}
}
}
Dispatcher.start()
例如(我不喜欢使用LinkedBlockingQueue,但我需要限制等待执行的最大进程数。当我在实际代码中使用此模式时,由于生成工作的方法(目录递归下降)而导致内存不足错误,添加文件的速度比处理文件的速度快。对于如何纯粹使用参与者来完成此操作,有何建议?
import scala.actors.{Actor, OutputChannel}
import scala.collection.mutable.Queue
case class Task(time: Long, i: Int)
case object GiveMeWork
case object Quit
case object OffDuty
object Dispatcher extends Actor {
println("Dispatcher created")
def act() {
val workers = (1 to 4).map(id => (new Worker(id)).start())
val waitingWorkers = Queue[OutputChannel[Any]](workers: _*)
val tasks = Queue[Task]()
var workSender: Option[OutputChannel[Any]] = None
loop {
react {
case GiveMeWork =>
if (!tasks.isEmpty) sender ! tasks.dequeue()
else waitingWorkers enqueue sender
workSender map { _ ! GiveMeWork }
workSender = None
case t: Task =>
if (!waitingWorkers.isEmpty) waitingWorkers.dequeue() ! t
else tasks enqueue t
if (tasks.length < 1000) sender ! GiveMeWork
else workSender = Some(sender)
case Quit =>
println("Told to quit")
workers.foreach{ _ ! Quit }
sender ! OffDuty
exit()
}
}
}
}
class Worker(id: Int)
extends Actor {
var jobs = 0
def act() {
loop {
react {
case t: Task =>
Thread.sleep(id)
jobs += 1
Dispatcher ! GiveMeWork
case Quit =>
println("Worker(" + id + ") completed " + jobs + " jobs")
sender ! OffDuty
exit()
}
}
}
}
Dispatcher.start()
for (i <- 0 until 5000) {
Thread.sleep(1)
Dispatcher !? Task(System.nanoTime(), i)
}
println("Telling Dispatcher to quit")
Dispatcher !? Quit