Skip to content

Commit 1bc62be

Browse files
committed
修改文章内容
1 parent 25b4168 commit 1bc62be

File tree

1 file changed

+46
-42
lines changed

1 file changed

+46
-42
lines changed

_posts/2018-06-28-RxJava2探索-讲得清道得明的线程切换原理之subscribeOn.md

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ this.threadWorker就是刚才我们说的IoScheduler.CachedWorkerPool提供给Io
641641

642642
#### 3.4.1 来一段非常非常simple的代码
643643

644-
先定义一个打印类,它内部可以持有一个其他的打印类source,在他的打印方法里会开启新线程执行source的打印方法
644+
先定义一个打印类,它内部可以持有一个其他的打印类source,在他的打印方法里,如果source不为空,会开启新线程执行source的打印方法,如果source为空,这不开启新线程执行source的打印方法
645645

646646
private static class Printer {
647647
Printer source;
@@ -652,6 +652,10 @@ this.threadWorker就是刚才我们说的IoScheduler.CachedWorkerPool提供给Io
652652

653653
}
654654
void print() {
655+
if(source==null){
656+
System.out.println(name +"-"+ Thread.currentThread().getName());
657+
return;
658+
}
655659
new Thread(new Runnable() {
656660
@Override
657661
public void run() {
@@ -681,14 +685,12 @@ this.threadWorker就是刚才我们说的IoScheduler.CachedWorkerPool提供给Io
681685
printer4-Thread-0
682686
printer3-Thread-1
683687
printer2-Thread-2
684-
printer1-Thread-3
688+
printer1-Thread-2
685689

686690

687691
如果你清楚了这里要表示的这个原理,你可能就已经猜到为什么subscribeOn方法只有第一次指定线程的地方是有效的,我就不用费口舌了,文章到此结束。。。不过,那是不可能的,说好了要再装几分钟的x,怎么可能这么快。产品经理快扶我一把,虽然手断了,但我还要撸代码。
688692

689-
言归正传,这个原理是什么?对于任意一个Printer而言,不管外面包裹了多少层新的线程去调用他的print方法,他的print方法里的执行语句的工作线程永远都是他的print方法里new的那个Thread。那么在这里,对于第一个printer而言,不管你们把我传递了多少层,最后你们调用我的print方法的时候,我print方法里的执行语句的工作线程只能是我new的那个Thread。
690-
691-
类似如下代码
693+
言归正传,这个原理是什么?对于任意一个Printer而言,不管外面包裹了多少个新的Printer去调用他的print方法,他的print方法里的执行语句的工作线程永远都是他下游的第一个Printer的print方法里new的那个Thread,因为第一个Printer的source为空,print方法里的输出语句就没有在被别的Thread包裹了。类似如下代码
692694

693695
new Thread(new Runnable() {
694696
@Override
@@ -708,7 +710,7 @@ this.threadWorker就是刚才我们说的IoScheduler.CachedWorkerPool提供给Io
708710
},"thread1").start();
709711

710712

711-
Thread.currentThread().getName()的结果永远是thread3。清楚了这一点,我们就可以愉快的继续往下讲了。
713+
Thread.currentThread().getName()的结果永远是thread3。这里代码执行顺序和RxJava实际的顺序刚好相反,因为RxJava是逆向向上调用的,大家注意区分就好了。总之就是,第一个Printer的print方法的执行线程,只能是被他下游的Printer控制,到了这段代码里,那句输出语句打印出的线程名称,肯定是他外层Thread的名称。的清楚了这一点,我们就可以愉快的继续往下讲了。
712714

713715
#### 3.4.2 Observable多次subscribeOn的流程类比
714716

@@ -729,68 +731,68 @@ Thread.currentThread().getName()的结果永远是thread3。清楚了这一点
729731

730732

731733
其次,定义一个Printer类来实现IPrinter接口
732-
733-
private static class Printer implements IPrinter {
734+
735+
private static class Printer implements IPrinter {
734736
private IPrinter source;
735737
private String name;
736-
private static volatile AtomicInteger createCount = new AtomicInteger(0);
737738

738-
Printer(IPrinter source,String name) {
739+
Printer(IPrinter source, String name) {
739740
this.source = source;
740-
this.name=name;
741+
this.name = name;
741742
}
742743

743744
@Override
744745
public void subscribe(IPaper paper) {
745-
//这个地方非常关键
746-
IPaper parent = new Paper(paper);
746+
//这个地方非常关键
747+
IPaper parent = new Paper(paper, name);
747748
preparePrint(parent);
748749
}
749750

750751
@Override
751752
public void preparePrint(IPaper paper) {
753+
System.out.println(name + " preparePrint on " +
754+
Thread.currentThread().getName());
755+
if (null == source) {
756+
print(paper);
757+
return;
758+
}
752759
new Thread(new Runnable() {
753760
@Override
754761
public void run() {
755-
System.out.println("Printer-" + name + "-preparePrint-" +
756-
Thread.currentThread().getName());
757762
if (null != source) {
758763
source.subscribe(paper);
759-
} else {
760-
print(paper);
761764
}
762765
}
763766
}).start();
764767
}
765768

766769
@Override
767770
public void print(IPaper paper) {
768-
System.out.println("Printer-" + name + "-startPrint-" +
771+
System.out.println(name + " start print work on " +
769772
Thread.currentThread().getName());
770-
paper.show();
773+
paper.show("哈哈哈哈哈");
771774
}
772775
}
773-
776+
774777
再定义一个Paper类实现IPaper接口
775-
776-
private static class Paper implements IPaper {
778+
779+
private static class Paper implements IPaper {
777780
private IPaper actual;
778-
private static volatile AtomicInteger createCount = new AtomicInteger(0);
779-
private int mId;
781+
private String printerName;
780782

781-
Paper(IPaper actual) {
783+
Paper(IPaper actual,String printerName) {
784+
this.printerName=printerName;
782785
this.actual = actual;
783786
}
784787

785788
@Override
786-
public void show() {
787-
actual.show(content);
788-
mId=createCount.incrementAndGet();
789-
System.out.println("Paper-" + mId + "-show-" +
789+
public void show(String content) {
790+
System.out.println( printerName+" print on paper , and work on " +
790791
Thread.currentThread().getName());
792+
actual.show(content);
791793
}
792-
}
793-
794+
}
795+
794796
最后在main方法调用
795797

796798
public static void main(String args[]) {
@@ -800,24 +802,26 @@ Thread.currentThread().getName()的结果永远是thread3。清楚了这一点
800802
final IPrinter printer4 = new Printer(printer3, "printer4");
801803
printer4.subscribe(new IPaper() {
802804
@Override
803-
public void show() {
804-
805+
public void show(String content) {
806+
System.out.println(content + " show on " +
807+
Thread.currentThread().getName());
805808
}
806809
});
807810
}
808811

809812

810813
输出结果如下
811814

812-
Printer-printer4-preparePrint-Thread-0
813-
Printer-printer3-preparePrint-Thread-1
814-
Printer-printer2-preparePrint-Thread-2
815-
Printer-printer1-preparePrint-Thread-3
816-
Printer-printer1-startPrint-Thread-3
817-
Paper-1-show-Thread-3
818-
Paper-2-show-Thread-3
819-
Paper-3-show-Thread-3
820-
Paper-4-show-Thread-3
815+
printer4 preparePrint on main//onSubscribe线程-main
816+
printer3 preparePrint on Thread-0//printer4 new的
817+
printer2 preparePrint on Thread-1//printer3 new的
818+
printer1 preparePrint on Thread-2//printer2 new的
819+
printer1 start print work on Thread-2
820+
printer1 print on paper , and work on Thread-2
821+
printer2 print on paper , and work on Thread-2
822+
printer3 print on paper , and work on Thread-2
823+
printer4 print on paper , and work on Thread-2
824+
哈哈哈哈哈 show on Thread-2
821825

822826
代码你们可以直接考出去运行的,看看我有没有说错。subscribeOn之所以只有第一次调用才有效,就是利用的类似这个demo展示的原理。顶层Observer发送数据的线程永远是第一次调用subscribeOn时指定的线程,因为数据的发射流程过程中,我们再也没有去切换过线程了,所以这其实很好理解的吧。
823827

0 commit comments

Comments
 (0)