注意:我解決的問題只有教育目的,我知道我想創建的抽象是容易出錯等,我不需要快速解決方案,我需要解釋。SyncVar傳輸生產者/消費者線程在斯卡拉
在這本書我讀有運動,指出我需要實現SyncVar它具有以下接口:
class SyncVar[T] {
def get(): T = ???
def put(x: T): Unit = ???
}
我的評論:好吧,似乎可以理解的,需要一定的同步變化,我可以放或得。
SyncVar對象用於在兩個或多個線程之間交換值。 在創建時,SyncVar對象爲空:
°調用get拋出一個異常
°調用看跌增加了價值,SyncVar對象 值添加到SyncVar對象後,我們可以說,它非空:
°調用get返回當前值,並把狀態改變爲空
°調用放拋出一個異常
我的想法:這是一個變量,它在調用get時拋出空值的異常,或者當我們有一個值時拋出異常,當我們調用get清除之前的值時。好像我需要使用Option。
所以我提供以下實現:
class SyncVar[T] {
var value: Option[T] = None
def get(): T = value match {
case Some(t) => this.synchronized {
value = None
t
}
case None => throw new IllegalArgumentException("error get")
}
def put(x: T): Unit = this.synchronized{
value match {
case Some(t) => throw new IllegalArgumentException("error put")
case None => value = Some(x)
}
}
def isEmpty = value.isEmpty
def nonEmpty = value.nonEmpty
}
我的評論: 同步方式調用put和get,還有的isEmpty和非空
下一個任務讓我困惑: 的由於SyncVar對象處於無效狀態時出現異常,因此以前練習中的SyncVar對象使用起來可能很麻煩, 。在SyncVar對象上實現 一對isEmpty和nonEmpty方法。然後, 實現一個生產者線程,該線程將一系列數字0傳輸到15 到打印它們的消費者線程。
據我瞭解,我需要兩個線程:
//producer thread that produces numbers from 1 to 15
val producerThread = thread{
for (i <- 0 until 15){
println(s"$i")
if (syncVar.isEmpty) {
println(s"put $i")
syncVar.put(i)
}
}
}
//consumer that prints value from 0 to 15
val consumerThread = thread{
while (true) {
if (syncVar.nonEmpty) println(s"get ${syncVar.get()}")
}
}
問: 但是這個代碼由確定性造成的,所以它有不同的結果每一次,當我需要從打印1號到15(按照正確的順序)。你能解釋我的解決方案有什麼問題嗎?
是的,你是對的,問題是,我不能保證'GET'將通過'consumerThread' put'後'被調用,甚至當我申請同步放''和'get'。我怎樣才能確保'put'調用消費者線程後肯定會調用'get'並將值設置爲'None? –
提示:您需要在'producerThread'中等待_wait_,直到'syncVar'爲空(反過來在'consumerThread'中)。你如何使用內部循環來做到這一點? –
謝謝你的提示,而不是爲我解決:) –