2010-02-21 16 views
6

Ce programme, après l'exécution de main(), ne se termine pas.Comment ajouter des acteurs scala à un programme existant sans interférer avec le comportement de terminaison normal?

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" 
    } 
} 

En raison de cet effet secondaire inattendu, à l'aide des acteurs peut être considéré comme intrusif.

En supposant que les acteurs doivent continuer à fonctionner jusqu'à la fin du programme, comment feriez-vous pour préserver le comportement original dans tous les cas de résiliation?

Répondre

7

Dans 2.8 il y a une classe DaemonActor qui le permet. Dans 2.7.x je vous pouvez pirater dans un planificateur personnalisé qui n'empêche pas l'arrêt même s'il y a encore des acteurs en direct, ou si vous voulez un moyen facile, vous pouvez appeler System.exit() à la fin de main.

Si vous considérez un acteur comme une sorte de thread léger, la plupart du temps, vous voulez qu'un acteur en direct empêche la fin du programme. Sinon, si vous avez un programme qui fait tout son travail dans les acteurs, vous devez avoir quelque chose sur le fil principal juste pour le garder en vie jusqu'à ce que tous les acteurs finissent.

+0

Merci. Je vais essayer 2.8 bêta –

4

Une fois le thread principal de l'exemple ci-dessus terminé, le programme avait toujours un thread non démon exécutant l'acteur. Il est généralement une mauvaise idée de terminer brutalement les threads en cours d'exécution en utilisant Thread.destroy() ou System.exit() car les résultats peuvent être très mauvais pour votre programme, y compris, mais sans s'y limiter, la corruption de données et les interblocages. C'est pourquoi les méthodes Thread.destroy() et similaires ont été déconseillées en Java pour la première fois. La bonne façon serait d'implémenter explicitement la logique de terminaison dans vos threads. Dans le cas des acteurs de Scala, cela revient à envoyer un message Stop à tous les acteurs en cours d'exécution et à les faire partir quand ils l'obtiennent. Avec cette approche, votre idée ressemblerait à ceci:

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() 
       } 
      } 
     } 
    } 
} 
+0

Hélas, la gestion de la vie de l'acteur manuellement est ce que je voulais éviter ... C'est intrusif, car je dois changer main(). –