2013-03-26 201 views
1

在scala中,我怎麼能告訴一個線程:sleep t seconds,或者直到收到消息?即最多t秒睡眠,但在t未結束的情況下醒來並且您收到特定消息。Scala:喚醒睡眠線程

+0

IIRC,有一個等待(超時超時)過載?如果是這樣,請等待某個對象,並通知()消息是否可用。 – 2013-03-26 10:49:31

回答

1

或者,您可以使用條件變量。

val monitor = new AnyRef 
var messageReceived: Boolean = false 

// The waiting thread... 

def waitUntilMessageReceived(timeout: Int): Boolean = { 
    monitor synchronized { 
     // The time-out handling here is simplified for the purpose 
     // of exhibition. The "wait" may wake up spuriously for no 
     // apparent reason. So in practice, this would be more complicated, 
     // actually. 
     while (!messageReceived) monitor.wait(timeout * 1000L) 
     messageReceived 
    } 
} 

// The thread, which sends the message... 

def sendMessage: Unit = monitor synchronized { 
    messageReceived = true 
    monitor.notifyAll 
} 
+0

但是隨機喚醒問題應該由while(!messageReceived)而不是if(!messageReceived)來處理,不是嗎? – user1377000 2013-03-26 11:26:49

+1

除非你別無選擇(例如,因爲性能很關鍵,必要的邏輯是非標準的),所以用手滾動這種解決方案是非常不合適的,因爲這太容易忘記。應該使用Scala和Java中的更高級別的構造。 – 2013-03-26 12:24:24

+0

@ user1377000 - 隨機喚醒由'while'處理,但超時行爲在我的建議中會出錯:在每次喚醒後,超時將以初始值再次開始。在最糟糕的情況下,這可能會導致「永遠等待」的情況。 – Dirk 2013-03-26 12:28:41

0

反而使其睡眠給定的時間,使其只醒來超時()味精,然後你可以,如果你想讓它「喚醒」過早地把這個消息。

3

答案在很大程度上取決於什麼消息。如果您使用的是演員(舊版本或Akka variety),那麼您可以簡單地聲明接收時的超時值。 (陣營是不是真的運行,直到它得到一個消息,所以你不能在其上放置超時。)

// Old style 
receiveWithin(1000) { 
    case msg: Message => // whatever 
    case TIMEOUT =>  // Handle timeout 
} 

// Akka style 
context.setTimeoutReceive(1 second) 
def receive = { 
    case msg: Message => // whatever 
    case ReceiveTimeout => // handle timeout 
} 

否則,究竟你的意思是「消息」?

一個簡單的方法來發送消息是使用的正是這種東西做了Java併發類。例如,你可以使用一個java.util.concurrent.SynchronousQueue存放消息,並且接收器可以調用poll方法,這需要超時:

// Common variable 
val q = new java.util.concurrent.SynchronousQueue[String] 

// Waiting thread 
val msg = q.poll(1000) 

// Sending thread will also block until receiver is ready to take it 
q.offer("salmon", 1000) 

ArrayBlockingQueue也是在這些情況下非常有用(如果你想發送者能夠將消息打包到緩衝區中)。