【发布时间】:2020-03-04 21:05:25
【问题描述】:
以下代码仅用于演示目的。这不是开发代码,所以请不要批评“不良做法”。它只是用来传达概念的。
假设你在一个方法中,有一个空列表。
public void myMethod() {
List<Strings> myList = new ArrayList<>();
}
在 myList 定义的正下方,进行了一个多线程异步 RX 调用,并带有一个用于返回结果的回调。让我们看看 Schedulers.io(),观察 AndroidSchedulers.mainThread()。
getMyStuff.subOn(Schedulers.io()).obsOn(AndroidSchedulers.mainThread()).subscribe(new Callback(){
@Override
public void onDone(List<String> list){
myList.addAll(list);
}
})
如果我们在其下方放置一个临时块,并尝试访问 myList,它将为 null。
Thread.wait(5000);
Assert.true(myList.size() > 0) --> False
但是,如果我们这样做,但从 主 线程访问它,它会工作。
Thread.wait(5000);
RunOnMainThread { //--> This can be done any number of ways.
Assert.true(myList.size() > 0) --> True
}
整个工作代码看起来像
public void myMethod() {
List<Strings> myList = new ArrayList<>();
getMyStuff.subOn(Schedulers.io()).obsOn(AndroidSchedulers.mainThread()).sub(new Callback(){
@Override
public void onDone(List<String> list){
myList.addAll(list);
}
})
Thread.wait(5000);
RunOnMainThread { //--> This can be done any number of ways.
Assert.true(myList.size() > 0) --> True
}
}
我目睹了在其他情况下发生的类似情况,但我不知道为什么。是因为每个线程都有自己的堆栈/内存区域吗?
【问题讨论】:
-
有趣!所以如果这是一个类变量,使用“volatile”会解决这个问题吗?
-
这激起了我的疑问。这不都是运气吗?主线程是一个活套线程,这意味着它可能不会立即执行,对吧?一旦工作开始运行,列表就会被初始化,这不是巧合吗?谢谢
-
这是因为您在主线程上更新
myList,然后在延迟一段时间后在主线程上安排大小检查。 -
如果您遵循这些步骤,这很容易重现。 “仅用于演示目的”是为了让人们不会抱怨不良做法,认为我正在使用计时器来处理异步行为。
-
等等,有一个
List<Strings> myList = null,但没有list = new ArrayList<>()或类似的......我知道这只是一个演示,但仍然......
标签: multithreading scope rx-java rx-java2 race-condition