Multithreading 带有后台任务的Scala命令行应用程序

Multithreading 带有后台任务的Scala命令行应用程序,multithreading,scala,background,task,command-line-interface,Multithreading,Scala,Background,Task,Command Line Interface,我正在用Scala开发一个命令行程序。一些命令将生成后台线程来执行某些工作。有些命令会产生线程,这些线程会以一定的延迟重复运行同一任务。我还需要一个stop命令来防止现有的后台任务重复(不需要终止它,只需在完成迭代后退出即可)。构造这种程序的最佳原语是什么 我正在考虑使用期货,例如下面的。你们觉得这个设计怎么样?您将如何实现这种功能 case class OneTimeTaskCommand(arg: String) case class StopTaskCommand(name: String

我正在用Scala开发一个命令行程序。一些命令将生成后台线程来执行某些工作。有些命令会产生线程,这些线程会以一定的延迟重复运行同一任务。我还需要一个stop命令来防止现有的后台任务重复(不需要终止它,只需在完成迭代后退出即可)。构造这种程序的最佳原语是什么

我正在考虑使用期货,例如下面的。你们觉得这个设计怎么样?您将如何实现这种功能

case class OneTimeTaskCommand(arg: String)
case class StopTaskCommand(name: String)
case class RepeatingTaskCommand(name: String, delay: Long, arg: String)

def runOneTimeTask(arg: String): Unit = { ... }
def runRepeatingTaskCommand(arg: String): Unit = { ... }

trait Scheduler {
    def schedule(name: String, delay: Long): Unit
    def unschedule(name: String): Unit
    def isScheduled(name: String): Boolean = repeatDelay(name).isDefined
    def repeatDelay(name: String): Option[Long]
}

def runCommand(command)(implicit scheduler: Scheduler): Future[Unit] = {
  command match {
    case OneTimeTaskCommand(arg) => Future(runOneTimeTask(arg))
    case StopTaskCommand(name) =>
        if (scheduler.isScheduled(name)) {
            scheduler.unschedule(name)
            Future.successful(())
        } else {
            Future.failure(new CommandException(s"task $name is not running"))
        }
    case RepeatingTaskCommand(name, delay, arg) =>
        /* function to generate repeating future */
        def createFuture(): Future[Unit] = {
            runRepeatingTaskCommand(arg)).flatMap { _ =>
                scheduler.repeatDelay(name) match {
                    case Some(d) =>
                        Thread.sleep(d)
                        Future(createFuture())
                    case None =>
                        Future.successful(())
                }
            }
        }

        /* spin off repeating task */
        if (scheduler.isScheduled(name)) {
            Future.failure(new CommandException(s"task $name is already running"))
        } else {
            scheduler.schedule(name, delay)
            createFuture()
        }
  }
}
上面的代码将集成到一些REPL中,该REPL读取用户输入并调用以下一些调用:

implicit val scheduler: Scheduler = new SchedulerImpl

runCommand(OneTimeTaskCommand(someArg))

// Run backgrounded task to be repeated every second
runCommand(RepeatingTaskCommand("backgrounded-task", 1000L, someArg))

// Stop backgrounded task
runCommand(StopTaskCommand("backgrounded-task"))

你可能想看看承诺。它们基本上是可完成的未来。因此,您的后台任务在完成时可以完成承诺,而您的主代码在将来准备好检查结果时可以加入。这种类型的问题可能更适合。是否有方法在Stack Exchange站点之间移动问题?:P