2010-07-16 101 views
3

我在玩RemoteActors。現在我想知道,如果關閉RemoteActor會發生什麼情況。 該演員已與RemoteActor.alive和RemoteActor.register一起使用。 我無法找到兩者的反轉:活動和註冊。RemoteActor取消註冊演員

如何正確關閉RemoteActor?

更新

爲了使它更加明顯,我做了一個 '小' 的例子。以下兩個程序都不終止,JVM一直運行。所有用戶創建的actor和main都已完成。

package test 

import scala.actors.{OutputChannel, AbstractActor, Actor} , Actor._ 
import scala.actors.remote.RemoteActor , RemoteActor._ 


object ActorTestA{ 
    def main(args :Array[String]) { 
    RemoteActor.classLoader = getClass().getClassLoader() 
    println("Start A") 
    val a = new A().start 
    println("Fin A") 
    } 
} 

object ActorTestB{ 
    def main(args :Array[String]) { 
    RemoteActor.classLoader = getClass().getClassLoader() 
    println("Start B") 
    val b = new B().start 
    b !? 'start 
    println("Fin B") 
    } 
} 

case class M1(sendRef :AbstractActor, m2 :M2) 
case class M2(v1:String, v2 :String, sendRef :AbstractActor) 
case class M3(m2 :M2) 

object A { val portToUse = 20000 } 
class A extends Actor { 
    alive(A.portToUse) 
    register('A, this) 
    val proxy = select(actors.remote.Node("localhost", A.portToUse), 'A) 

    def act = { 
    loop { react { 
     case M1(sendRef, m2) => 
     println("A receives M1") 
     sendRef ! M3(m2) 
     self ! 'exit 
     case 'exit => 
     println("A exits") 
     exit 
     case any => println("Unknown Msg: "+any) 
    } } 
    } 
} 


class B extends Actor { 
    val portToUse = 20001 
    alive(portToUse) 
    register('B, this) 
    val proxy = select(actors.remote.Node("localhost", portToUse), 'B) 

    var resultTo :OutputChannel[Any] = _ 
    def act = { 
    loop { react { 
     case 'start => 
     println("B starts") 
     val a = select(actors.remote.Node("localhost", A.portToUse), 'A) 
     a ! M1(proxy, M2("some","val", proxy)) 
     resultTo = sender 
     case M3(M2(v1,v2,sendRef))=> 
     println("B receives M3") 
     resultTo ! sendRef 
     self ! 'exit 
     case 'exit => 
     println("B exits") 
     exit 
     case any => println("Unknown Msg: "+any) 
    } } 
    } 
} 

輸出,適用於爲:

Start A 
Fin A 
A receives M1 
A exits 

而對於B是:

Start B 
B starts 
B receives M3 
B exits 
Fin B 

調試器說,對某個程序時,下面的4個非守護線程仍有上漲:

  • PlainSocketImpl.socketAccept
  • SocketInputStream.socketRead0
  • ForkJoinScheduler.liftedTree1
  • DestroyJavaVM

回答

1

Actor。鏈路和Actor .trapExit你在找什麼?

編輯試試這個。我把所有的東西都轉化爲行爲方法。在遠程角色之間發送代理似乎也會導致問題。有一些關於這個可能的bug的討論:http://www.scala-lang.org/node/6779;請參閱Stefan Kuhn的評論。

package test 

import scala.actors.{OutputChannel, AbstractActor, Exit, Debug, Actor} , Actor._ 
import scala.actors.remote.RemoteActor , RemoteActor._ 


object ActorTestA{ 
    def main(args :Array[String]) { 
    println("Start A") 
    val a = new A().start 
    println("Fin A") 
    } 
} 

object ActorTestB{ 
    def main(args :Array[String]) { 
    println("Start B") 
    val b = new B().start 
    b ! 'start 
    println("Fin B") 
    } 
} 

case class AA(hostname: String, port: Int, symbol: Symbol) { 
    def proxy = select(actors.remote.Node(hostname, port), symbol) 
} 
case class M1(sendRef :AA, m2 :M2) 
case class M2(v1:String, v2 :String, sendRef :AA) 
case class M3(m2 :M2) 

object A { val portToUse = 20000 } 
class A extends Actor { 
    def act = { 
    alive(A.portToUse) 
    register('A, this) 
    RemoteActor.classLoader = getClass().getClassLoader() 
    val proxy = select(actors.remote.Node("localhost", A.portToUse), 'A) 

    loop { react { 
     case M1(sendRef, m2) => 
     println("A receives M1") 
     sendRef.proxy ! M3(m2) 
     self ! 'exit 
     case 'exit => 
     println("A exits") 
     exit 
     case any => println("Unknown Msg: "+any) 
    } } 
    } 
} 


class B extends Actor { 
    def act = { 
    RemoteActor.classLoader = getClass().getClassLoader() 
    val portToUse = 20001 
    alive(portToUse) 
    register('B, this) 
    var proxy = AA("localhost", portToUse, 'B) 
    var resultTo :Option[OutputChannel[Any]] = None 

    loop { react { 
     case 'start => 
     println("B starts") 
     val a = select(actors.remote.Node("localhost", A.portToUse), 'A) 
     a ! M1(proxy, M2("some","val", proxy)) 
     resultTo = Some(sender) 
     case M3(M2(v1,v2,sendRef))=> 
     println("B receives M3") 
     resultTo match { 
      case Some(ch) => ch ! sendRef.proxy; 
      case None => println("ch missing!?") 
     } 
     self ! 'exit 
     case 'exit => 
     println("B exits") 
     exit 
     case any => println("Unknown Msg: "+any) 
    } } 
    } 
} 
+0

不,Actor.link和trapExit用於通知鏈接的角色是否另一個鏈接的角色終止。這對RemoteActors現在不起作用。 – 2010-07-16 16:16:47

+0

我必須將ActionActor.classLoader = getClass()。getClassLoader()移動到act方法以外才能運行您的代碼。有用。發送代理是問題的根源。謝謝。 – 2010-07-20 13:46:33