[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秒内。
总感觉被骗了。
相关文章推荐
- Android休眠设置时间
- Android5.0后外置SDCard读写
- VelocityTracker的用法
- android sdk manager不显示更新,只显示已安装,解决办法
- android多线程及异步处理
- Android逆向---Fiddler简易使用教程之使用(2)
- Android使listview(GridView) 获取焦点时,选中上次失去焦点时的item,而不是就近的item
- Android具有system权限为什么不可以访问SDcard
- Android逆向---Fiddler简易使用教程之配置环境(1)
- 实现ListView的弹性效果,下拉隐藏ToolBar(ActionBar),上拉显示ToolBar
- Android-BaseLine框架初识之如何使用(二)
- GridView & ListView (Android盒子开发)
- android系统源码查看地址
- 实例介绍 Java(android) 回调函数使用方法
- 前言:一步一步开发安卓应用
- android不用root删除系统apk
- android textview改变部分文字的颜色和string.xml中文字的替换
- android-设置状态栏与标题栏背景
- android 后台service开机自启动
- Android实现通讯录效果――获取手机号码和姓名