您的位置:首页 > 移动开发 > Android开发

[Android]newCahcedThrealPool源码解析

2016-03-11 11:20 363 查看

介绍

大家肯定用过
Executors
详细文档点这

Executors
有创建四种线程池的方法

newFixedThreadPool
,固定线程数的线程池;

newSingleThreadExecutor
,单线程池;

newCachedThreadPool
,若不存在可重用的线程,则新建,否则复用;

newScheduledThreadPool
,线程可延时或周期启动的线程池。

单看描述很容易理解每种线程池的含义,但思考一下线程为什么可以复用?

真的是线程执行完毕之后把它再回收利用吗?

我们通过源码来解析一下
newCachedThreadPool
真正实现“复用”的原理。

下面源码只展现重要代码

源码一览

通过
Executors.newCachedThreadPool()
点进去

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}


初始化变量,没什么花头。看一眼注释,注意到
ThreadFactory
这个参数用于创建
Thread
,而对于不同的线程池,都实现了各自的
ThreadFactory


对于
newCachedThreadPool
,它使用
Executors.defaultThreadFactory()
打开其源码

static class DefaultThreadFactory implements ThreadFactory {
·····································
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
·································
return t;
}
}


关注
newThread()
方法,什么鬼,明明每次都新建线程嘛。

思考一下线程都会执行
execute()
方法,可能里面还有神奇的魔法?

点开
ThreadPoolExecutor.execute()
方法

public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}


瞄一眼注释和代码,都跟
addWorker
有关。
Worker
ThreadPoolExecutor
的一个静态内部类,实现了
Runnble
,同时持有
Thread
Runnable
,可以简单看作需要执行的任务。

addWorker
函数太长了,主要功能是向
SynchronousQueue
中添加
Worker
对象,成功后执行
Thread.start()


既然
Worker
就是任务,再看到
Worker.run()
方法

final void runWorker(Worker w) {
`````````some code`````````````
try {
while (task != null || (task = getTask()) != null) {
`````````````run task``````````````
}
} finally {
processWorkerExit(w, completedAbruptly);
}
}


此时任务已提交,线程已经新建(纯粹的new)出来

注意到
while
循环,任务是从
getTask()
中取出来的

private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?

for (;;) {
`````````````pass````````````````````
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}


注意
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)
,会检查任务队列里是否存在任务,超时60秒,若超时则退出。

线程缓存了吗?

假设A线程执行A任务,A任务被取消,B任务在60秒内提交,A线程被重用,而61秒后,B线程被新建。

总而言之,重用发生在这60秒内。

总感觉被骗了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: