Эта программа, после выполнения основного (), не выходит.
object Main
{
def main(args: Array[String]) {
... // existing code
f()
... // existing code
}
def f() {
import scala.actors.Actor._
val a = actor {
loop {
react {
case msg: String => System.out.println(msg)
}
}
}
a ! "hello world"
}
}
Из-за этого неожиданного побочного эффекта, с помощью агентов может быть просмотрен как навязчивый.
Принятие агентов должно продолжить работать до завершения программы, как Вы сделали бы для сохранения исходного поведения во всех случаях завершения?
В 2.8 есть класс DaemonActor, который позволяет это сделать. В 2.7.x вы можете встроить собственный планировщик, который не предотвращает выключение, даже если все еще есть живые акторы, или, если вы хотите простой способ, вы можете вызвать System.exit() в конце main.
Если вы рассматриваете актор как нечто вроде легковесного потока, то в большинстве случаев вам нужен живой актор, чтобы предотвратить завершение программы. В противном случае, если у вас есть программа, которая выполняет всю свою работу в акторах, вам потребуется что-то на главном потоке, чтобы он оставался живым, пока все акторы не закончат свою работу.
После завершения основного потока в приведенном выше примере в программе все еще оставался недемонский поток, запускающий актера. Обычно это плохая идея - грубо завершать запущенные потоки с помощью Thread.destroy() или System.exit(), поскольку результаты могут быть очень плохими для вашей программы, включая, но не ограничиваясь, повреждение данных и тупики. Именно поэтому Thread.destroy() и аналогичные методы были в первую очередь устаревшими в Java. Правильным способом будет явная реализация логики завершения в ваших потоках. В случае с акторами Scala это сводится к отправке сообщения Stop всем запущенным акторам, и заставить их завершить работу, когда они его получат. При таком подходе ваш пример будет выглядеть так:
object Main
{
case object Stop
def main(args: Array[String]) {
... // existing code
val a = f()
a ! "hello world"
... // existing code
a ! Stop
}
def f() = {
import scala.actors.Actor._
actor {
loop {
react {
case msg: String => System.out.println(msg)
case Stop => exit()
}
}
}
}
}