}
也许你会问,这确定有问题?通过Looper
在子线程弹出一个Toast
,这不是很正常的一件事?经常这么干,从来没出现任何问题,为啥到你这就出问题?
我让妹子把Looper
及Toast
代码注释掉,if语句里面只保留一行startActivity
,妹子试后开心的跟我说,好了,没问题了,这怎么解释?
Looper
一脸委屈的说道:你说我是凶手,我就是凶手了,证据呢?
ok,我们就来寻找证据,我们知道,Looper.loop()
方法内部,会开启一个死循环,如下:
public static void loop() {
//省略部分代码
for (;😉 {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//省略部分代码
}
//省略部分代码
}
可以看到,queue.next()
这行代码官方注释了,有可能会被堵塞,什么时候会堵塞?没有消息的时候,可见,调用Looper.loop()
方法所在的线程会进入死循环。
那这个和我们的案件有什么关系呢?
这就要来说说RxJava
的线程池了,上面TokenInterceptor
回调所在的线程是RxJava
的IO线程,而RxJava的IO线程池的配置,却仅允许一条核心线程执行任务,当任务在执行,其它任务过来时,必须等待至上一个任务结束。
在IoScheduler
类中可以找到静态内部类ThreadWorker
,ThreadWorker
继承至NewThreadWorker
,在该类中,我们可以找到线程池对象,如下:
public class NewThreadWorker extends Scheduler.Worker implements Disposable {
private final ScheduledExecutorService executor;
//省略部分代码
public NewThreadWorker(ThreadFactory threadFactory) {
//这里创建了线程池
executor = SchedulerPoolFactory.create(threadFactory);
}
//省略部分代码
}
SchedulerPoolFactory.create方法点进去看看
public static ScheduledExecutorService create(ThreadFactory factory) {
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory); //核心线程数量为1
//省略部分代码
return exec;
}
可以看到,这里传了个1,就是核心线程的数量,继续往下看,最终找到了创建线程池对象代码,如下:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
这里简单解读一下,该线程池核心线程数量为1,非核心线程数量无上限,非核心线程闲置时间超过10毫秒便会被回收,并使用了延迟队列。
注意注意,前方高能预警
用简单的话来说,该线程池,同一时间,仅会执行一个任务,也就是串行,这也就解释Looper
与本案的关系,因为Looper.loop()
所在线程进入死循环,该线程所在线程池收到其它任务时,便必须得等待至上一个任务执行完毕,然而上一个任务在死循环,所以下一个任务永远得不到执行,这也就是为什么请求代码执行了,请求却没发出去原因。
到这,估计很多人会有疑问
RxJava的Io线程池,是串行执行的,那么它又是如何做到并行的呢?难道以前写的并行代码,其实都是串行实现的?
线程池已经有任务在执行了,为啥还会拿到该线程池执行新的任务呢?
RxJava为啥不使用OkHttp内部的线程池配置,只要有任务来,都开启非核心线程去执行?
ok,接下来一一解答
首先,第一个,RxJava
如何根据目前的Io线程池,做到并行任务?
其实很简单,在IoScheduler的静态内部类CachedWorkerPool
中,维护了一个线程池队列,每次收到新任务,都会从队列里面取出一个线程池去执行任务,如果没有,则创建一个新的线程池,如下:
static final class CachedWorkerPool implements Runnable {
//这个就是线程池队列
private final ConcurrentLinkedQueue expiringWorkerQueue
final CompositeDisposable allWorkers;
private final ThreadFactory threadFactory;
//省略部分代码
//取出一个线程池
ThreadWorker get() {
if (allWorkers.isDisposed()) {
return SHUTDOWN_THREAD_WORKER;
}
while (!expiringWorkerQueue.isEmpty()) {
ThreadWorker threadWorker = expiringWorkerQueue.poll();
if (threadWorker != null) {
return threadWorker; //队列里有,直接返回
}
}
// 队列没有,创建一个新的
ThreadWorker w = new ThreadWorker(threadFactory);
allWorkers.add(w);
return w;
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
133965)]
[外链图片转存中…(img-KLzFUNVB-1710945133966)]
[外链图片转存中…(img-wEUsej0j-1710945133966)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-iykvp9dd-1710945133966)]