【问题标题】:RxJava and Multi-threaded VariablesRxJava 和多线程变量
【发布时间】: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&lt;Strings&gt; myList = null,但没有list = new ArrayList&lt;&gt;() 或类似的......我知道这只是一个演示,但仍然......

标签: multithreading scope rx-java rx-java2 race-condition


【解决方案1】:

我很惊讶您没有收到 myList 超出范围的编译器警告。它应该被声明为静态或移动到 Class 范围。由于对 sub 的调用是异步的,因此响应将到达 myMethod 范围之外的另一个线程。

【讨论】:

    猜你喜欢
    • 2017-11-15
    • 1970-01-01
    • 2013-07-08
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多