簡體   English   中英

具有超時的RxScala遞歸流

[英]RxScala recursive stream with timeout

我試圖遞歸定義一個可觀察對象,該對象從某個主題發出項目,或者如果經過一定時間,則使用默認值,在這種情況下,我使用的是計時器的默認值零。 我正在使用RxScala,並從以下代碼開始:

val s = PublishSubject[Int]()

def o: Observable[Unit] = {
  val timeout = Observable.timer(1 second)
  Observable.amb(s, timeout)
    .first
    .concatMap((v) => {
      println(v)
      o
    })
}

ComputationScheduler().createWorker.schedule {
  var value = 0
  def loop(): Unit = {
    Thread.sleep(5000)
    s.onNext(value + 1)
    value += 1
    loop()
  }
  loop()
}

o.toBlocking.last

這似乎應該工作,但輸出令人困惑。 每隔零個序列包含兩個,而不是預期的四個。 發射兩個零,剩余的三秒鍾過去了,但是沒有輸出。

0
0
0
0
1
0
0
2
0
0
0
0
3
0
0
4
0
0
0
0
5
0
0
6
0
0
0
0
7
0
0
8

這確實令人費解! 所以這是一個理論:

  1. 實際上,您的代碼每5秒產生4個滴答聲,而不是5個。
  2. 第四名是比賽條件,一個是先通過超時獲勝,然后是工人,然后是超時,依此類推。

因此,而不是序列為00001 002 00003 ...將其視為0000 1002 0000 ...

因此,您可能在這里遇到2個獨立的問題,如果不擺弄它,我將無能為力,但是您可以嘗試做的事情:

  1. 還要在o()中添加一個序列號,這樣您就可以查看哪些計時碼未贏得比賽。
  2. 將值從1秒和5秒更改為彼此不成倍的值,例如1.5和5。這可能有助於您解決一個問題,並專注於另一個問題。
  3. 讓外部無關的工作者每秒打印“ ----”。 0.3秒左右后啟動。 可能會讓您更好地了解鴻溝在哪里。

將代碼重構為以下代碼(在我的機器上)會產生預期的結果:

object Test {
  def main(args: Array[String]) {
    val s = PublishSubject[Int]()

    val timeout = Observable.timer(1 second)

    def o: Observable[Unit] = {
      Observable.amb(s, timeout).first
        .concatMap((v) => {
          println(v)
          o
        })
    }

    var value = 0
    NewThreadScheduler().createWorker.scheduleRec {
      Thread.sleep(5000)
      value += 1
      s.onNext(value)
    }

    o.toBlocking.last
  }
}

注意切換到NewT​​hreadScheduler並使用scheduleRec方法,而不是手動遞歸調度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM