android 的多线程 实现方法,android 线程的高级使用( 七 )


前面可以看到,runWorker是执行在子线程内部,主要执行了三件事:
分析1:获取当前线程,当执行shutdown()时需要将线程interrupt(),接下来从Worker内部取到firstTask,即execute传入的runnable,接下来会执行;
分析2:while循环,task不空直接执行;否则执行getTask()去获取,不为空直接执行;
分析3:对有效的task执行run(),由于是在子线程中执行,因此直接run()即可,不需要start();
前面看到,在while内部有执行getTask(),一起看一下:
getTask()是从workQueue内部获取接下来需要执行的runnable , 内部主要做了两件事:
分析1:先获取到当前正在执行工作的线程数量wc,通过判断allowCoreThreadTimeOut[在创建ThreadPoolExecutor时可以进行设置]及wc > corePoolSize来确定timed值;
分析2:通过timed值来决定执行poll()或者take() , 如果WorkQueue中有未执行的线程时,两者作用是相同的,立刻返回线程;如果WorkQueue中没有线程时,poll()有超时返回,take()会一直阻塞;如果allowCoreThreadTimeOut为true,则核心线程在超时时间没有使用的话,是需要退出的;wc > corePoolSize时,非核心线程在超时时间没有使用的话,是需要退出的;
allowCoreThreadTimeOut是可以通过以下方式进行设置的:
如果没有进行设置,那么corePoolSize数量的核心线程会一直存在 。
总结一下:ThreadPoolExecutor内部的核心线程如何确保一直存在,不退出?
上面分析已经回答了这个问题,每个线程在执行时会执行runWorker(),而在runWorker()内部有while()循环会判断getTask(),在getTask()内部会对当前执行的线程数量及allowCoreThreadTimeOut进行实时判断,如果工作数量大于corePoolSize且workQueue中没有未执行的线程时,会执行poll()超时退出;如果工作数量不大于corePoolSize且workQueue中没有未执行的线程时,会执行take()进行阻塞,确保有corePoolSize数量的线程阻塞在runWorker()内部的while()循环不退出 。
如果需要关闭线程池,需要如何操作呢,看一下shutdown()方法:
以上可以看到,关闭线程池的原理:a. 遍历线程池中的所有工作线程;b. 逐个调用线程的interrupt()中断线程(注:无法响应中断的任务可能永远无法终止)
也可调用shutdownNow()来关闭线程池 , 二者区别:
shutdown():设置线程池的状态为SHUTDOWN , 然后中断所有没有正在执行任务的线程;
shutdownNow():设置线程池的状态为STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表;
使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow();
总结一下:ThreadPoolExecutor在执行execute()及shutdown()时的调用关系,流程图如下:

线程池可以通过Executors来进行不同类型的创建,具体分为四种不同的类型 , 如下:
可缓存线程池:不固定线程数量,且支持最大为Integer.MAX_VALUE的线程数量:
1、线程数无限制
2、有空闲线程则复用空闲线程,若无空闲线程则新建线程
3、一定程度上减少频繁创建/销毁线程,减少系统开销
固定线程数量的线程池:定长线程池
1、可控制线程最大并发数(同时执行的线程数)
2、超出的线程会在队列中等待 。
单线程化的线程池:可以理解为线程数量为1的FixedThreadPool
1、有且仅有一个工作线程执行任务
2、所有任务按照指定顺序执行,即遵循队列的入队出队规则
定时以指定周期循环执行任务
【android 的多线程 实现方法,android 线程的高级使用】 一般来说 , 等待队列 BlockingQueue 有: ArrayBlockingQueue 、 LinkedBlockingQueue 与 SynchronousQueue。