배우

2013-11-09 2 views
3

내부 Thread.sleep를 호출하면 기본적으로 내가이 (간체)과 같은 기능 재시도있다. 내가 들었는데, 그것은 배우 내부 Thread.sleep(123) 전화를 허용 아니다 : 그래서 만약배우

class MyActor extends Actor { 
    //...... 
    def someFunc = { 
    SomeObject.retry(5)(someRequestToServer) // ops, SomeObject.retry uses Thread.sleep! 
    } 

} 

: 분명히

class MyActor extends Actor { 
    //...... 
    def someFunc = { 
    Thread.sleep(456) // it's not acceptable in an actor, there is another way to do it 
    } 

} 

, 나는 클라이언트가 배우 내부 SomeObject.retry을 사용할지 여부를 모른다 방금 추가 :

res match { 
     case Some(x) => Some(x) 
     case None => 
     if (n > 1) 
      //make it sleep for a little while 
      Thread.sleep(123) // ops, what if it's being called inside an actor by a client?! 
      retry(n - 1)(fn) 
     else None 
    } 
    } 

그것은 합리적이지 않습니까? 그렇지 않다면 어떻게해야합니까?

답변

5

예, Thread.sleep을 호출하는 것은 나쁜 생각입니다. 시스템에서 스레드는 일반적으로 액터간에 공유되는 제한된 리소스입니다. 당신은 잠을 자면서 다른 액터로부터 스레드를 쫓아 내기를 원하지 않습니다.

Scheduler (docs 참조)을 사용하면 배우가 나중에 다시 시도 할 메시지를 보내도록 할 수 있습니다. SomeObject.attempt은 어디에서 이렇게하려면, 당신은 당신이 배우의 SomeObject.try 외부를 사용한다면 SomeObject에서 다음 Actor

class MyActor extends Actor { 

    import context.system.dispatcher 

    def receive = { 
    case DoIt(retries) if retries > 0 => 
     SomeObject.attempt(someRequestToServer) match { 
     case Some(x) => ... 
     case None => 
      context.system.scheduler.scheduleOnce(5.seconds, self, DoIt(retries - 1)) 
     } 
    } 

} 

에 시스템

def attempt(retries: Int) = { 
    SomeObject.attempt(someRequestToServer) match { 
    case Some(x) => ... 
    case None if retries > 0 => { 
     Thread.sleep(123) 
     attempt(retries - 1) 
    } 
    } 
} 

을 재시도 코드를 이동해야합니다 :

object SomeObject { 
    def attempt[T](fn: => T): Option[T] = 
    try { 
     Some(fn) 
    } catch { 
     case _: Exception => None 
    } 
} 
+0

'SomeObject.attempt'에서 모든 코드를 이동하면'SomeObject.attempt' 메서드에 남은 코드는 무엇입니까? –

+0

많이 없습니다. '시도 '에 남아있는 것은'None' 또는'Some'을 반환하는'retry' 메쏘드에서'catch'가 될 것입니다. 액터 시스템에서 기다리거나 다시 시도 할 코드는 순전히 멀티 스레드 시스템에서 기다리거나 다시 시도 할 코드와 상당히 다르기 때문에 재사용 가능한 공통 코드를 두 개에서 꺼내기가 매우 어렵습니다. – theon

+0

전체 예제를 보여 주시겠습니까? 1) SomeObject.attempt 2) def 시도 (...) case Some (x) => ... –