RxScala带超时的递归流
我试图递归地定义一个可观察的对象,它要么从一个主体发出项目,要么,如果经过一定的时间,一个默认值,在这种情况下,我使用计时器的默认值零。我正在使用RxScala,并从以下代码开始:RxScala带超时的递归流,scala,reactive-programming,rx-java,rx-scala,Scala,Reactive Programming,Rx Java,Rx Scala,我试图递归地定义一个可观察的对象,它要么从一个主体发出项目,要么,如果经过一定的时间,一个默认值,在这种情况下,我使用计时器的默认值零。我正在使用RxScala,并从以下代码开始: val s = PublishSubject[Int]() def o: Observable[Unit] = { val timeout = Observable.timer(1 second) Observable.amb(s, timeout) .first .concatMap((v
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
这确实令人费解!所以这里有一个理论: 事实上,您的代码每5秒产生4次滴答声,而不是5次。 4号有一个竞赛条件,首先是超时,然后是工人,然后是超时,等等。 所以,序列不是00001002 00003。。。将其视为0000 1002 0000 因此,您可能会遇到两个不同的问题,如果不加以处理,我无法做很多事情,但您可以尝试: 在o中添加一个序列号,这样您就可以看到哪些TIMOUT没有赢得比赛。 将值从1秒和5秒更改为彼此不是倍数的值,如1.5秒和5秒。这可能有助于你解决一个问题,集中精力解决另一个问题。 每秒打印一个无关的外部工作程序。大约在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
}
}
请注意切换到NewThreadScheduler并使用scheduleRec方法,而不是手动递归调度。感谢您的输入。今天晚上我还要玩一些。