我正试图了解在项目反应堆为应用程序代码提供的数据可见性方面有哪些保证。例如我希望下面的代码失败,但不会经过一百万次迭代。我正在更改线程A上典型POJO的状态,并从线程B读取它。Reactor是否保证POJO更改在线程间可见?
public class Main {
public static void main(String[] args) {
Integer result = Flux.range(1, 1_000_000)
.map(i -> {
Data data = new Data();
data.setValue(i);
data.setValueThreeTimes(i);
data.setValueObj(i + i);
return data;
})
.parallel(250)
.runOn(Schedulers.newParallel("par", 500))
.map(d -> {
d.setValueThreeTimes(d.getValueThreeTimes() + d.getValue());
return d;
})
.sequential()
.parallel(250)
.runOn(Schedulers.newParallel("par", 500))
.map(d -> {
d.setValueThreeTimes(d.getValueThreeTimes() + d.getValue());
return d;
})
// .sequential()
.map(d -> {
if (d.getValue() * 3 != d.getValueThreeTimes()) throw new RuntimeException("data corrupt error");
return d;
})
.reduce(() -> 0, (Integer sum, Data d) -> sum + d.getValueObj() + d.getValue())
.sequential()
.blockLast();
}
static class Data {
private int value;
private int valueThreeTimes;
private Integer valueObj;
public int getValueThreeTimes() {
return valueThreeTimes;
}
public void setValueThreeTimes(int valueThreeTimes) {
this.valueThreeTimes = valueThreeTimes;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "Data{" +
"value=" + value +
", valueObj=" + valueObj +
'}';
}
public void setValue(int value) {
this.value = value;
}
public Integer getValueObj() {
return valueObj;
}
public void setValueObj(Integer valueObj) {
this.valueObj = valueObj;
}
}
private static <T> T identityWithThreadLogging(T el, String operation) {
System.out.println(operation + " -- " + el + " -- " +
Thread.currentThread().getName());
return el;
}
}
答案 0 :(得分:1)
对于Flux
或Mono
(Publisher
)(onNext
),Reactive Streams规范要求事件必须是连续的。
parallel()
是ParallelFlux
,它通过分而治之的方式稍微放松了一点:您获得了多个“导轨”,每个导轨都分别遵循规格,但总体上没有(导轨之间的平行度) )。
依次,sequential()
返回到Flux
世界,并引入了内存屏障以确保所得序列符合RS规范。