Как я могу добавить акторов scala в существующую программу, не мешая нормальному поведению завершения? - PullRequest
6 голосов
/ 21 февраля 2010

Эта программа после выполнения main () не завершается.

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 ]

7 голосов
/ 21 февраля 2010

В 2.8 есть класс DaemonActor, который позволяет это. В 2.7.x I вы могли взломать собственный планировщик, который не предотвращает выключение, даже если все еще есть живые акторы, или если вы хотите простой способ, вы можете вызвать System.exit () в конце main.

Если вы думаете об актере как о легком потоке, большую часть времени вы хотите, чтобы живой актер предотвращал завершение программы. В противном случае, если у вас есть программа, которая выполняет всю свою работу в актерах, вам нужно что-то сделать в главном потоке, чтобы поддерживать ее до тех пор, пока все актеры не закончат.

4 голосов
/ 22 февраля 2010

После завершения основного потока в вышеприведенном примере программа все еще имела поток, не являющийся демоном, выполняющий актер.Обычно плохая идея жестоко прекратить выполнение потоков с помощью 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()
                }
            }
        }
    }
}
...