在并发情况下,不推荐使用通常的Subject对象,而是推荐使用SerializedSubject,并发时只允许一个线程调用onnext等方法!
官方说明:
<code class="hljs oxygene has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">When you use an ordinary Subject <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> a Subscriber, you must <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">take</span> care <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> call its Subscriber.onNext <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">method</span> <span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> its other <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span> methods)</span> <span class="hljs-title" style="box-sizing: border-box;">from</span> <span class="hljs-title" style="box-sizing: border-box;">multiple</span> <span class="hljs-title" style="box-sizing: border-box;">threads</span>, <span class="hljs-title" style="box-sizing: border-box;">as</span> <span class="hljs-title" style="box-sizing: border-box;">this</span> <span class="hljs-title" style="box-sizing: border-box;">could</span> <span class="hljs-title" style="box-sizing: border-box;">lead</span> <span class="hljs-title" style="box-sizing: border-box;">to</span> <span class="hljs-title" style="box-sizing: border-box;">non</span>-<span class="hljs-title" style="box-sizing: border-box;">serialized</span> <span class="hljs-title" style="box-sizing: border-box;">calls</span>, <span class="hljs-title" style="box-sizing: border-box;">which</span> <span class="hljs-title" style="box-sizing: border-box;">violates</span> <span class="hljs-title" style="box-sizing: border-box;">the</span> <span class="hljs-title" style="box-sizing: border-box;">Observable</span> <span class="hljs-title" style="box-sizing: border-box;">contract</span> <span class="hljs-title" style="box-sizing: border-box;">and</span> <span class="hljs-title" style="box-sizing: border-box;">creates</span> <span class="hljs-title" style="box-sizing: border-box;">an</span> <span class="hljs-title" style="box-sizing: border-box;">ambiguity</span> <span class="hljs-title" style="box-sizing: border-box;">in</span> <span class="hljs-title" style="box-sizing: border-box;">the</span> <span class="hljs-title" style="box-sizing: border-box;">resulting</span> <span class="hljs-title" style="box-sizing: border-box;">Subject</span>. </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
大致意思是当我们使用普通的Subject,必须要注意不要在多线程情况下调用onNext 方法,这样是违反了Observable 协议并且会导致执行结果返回带有有歧义的值(线程并发导致返回值混淆了)!
<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">To</span> protect a Subject <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> this danger, you can convert it <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> a SerializedSubject <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> code <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">like</span> the following: mySafeSubject = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SerializedSubject( myUnsafeSubject ); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
官方文档说的很明白了,只需要使用SerializedSubject封装原来的
Subject即可!!
测试demo:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MultiThread</span> {</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> InterruptedException { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PublishSubject<Integer> subject = PublishSubject.create(); subject.subscribe(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Action1<Integer>() { <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">call</span>(Integer t) { System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"======onnext===>value:"</span> + t + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">",threadId:"</span> + Thread.currentThread().getId()); } }); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SerializedSubject<Integer, Integer> ser = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SerializedSubject<Integer, Integer>(subject); <span class="hljs-keyword" style="color: rgb(0, 0, 136); b