/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
[写在前面]以下内容是看《Android 开发艺术探索》时做的笔记,其中也会有自己的一些思考和代码验证。
主线程和子线程
主线程: Android主的主线程也是
UI
线程,用来运行四大组件和处理它们与用户之间的操作。 子线程: 执行耗时的操作,如网络请求或IO操作。Android 3.0开始就要求所有的网络请求都必须在子线程中,否则会报NetworkOnMainThreadException
线程形态
AsyncTask
在后台执行耗时作务,并将执行的进度和最终结果传递给主线程,并在主线程中更新UI
public abstract class AsyncTask<Params, Progress, Result>
4个核心方法如下:
params
代表输入参数,方法中可以通过publishProgress
方法来更新进度,publishProgress
会调用onProgressUpdate
方法。此方法执行完后返回执行结果给onPostExecute
需要注意的
execute
方法executeOnExecutor
方法。HandlerThread
继承自Thread, 是一种可以使用Handler的Thread。其内部会有一个
Looper
,其run
方法开启Looper
的消息循环. 它的使用:IntentService
IntentService
继承自Service
并且是一个抽象类。IntentService
可以用于执行后台耗时的作务,当作务执行后会自动停止,由于它是服务的原因,因此它的优先级比单纯的线程要高很多,也就意味着不容易被系统杀死。IntentService
封装了Handler
和HandlerThread
intents
传递到onStartCommand
intent
传递到onHandleIntent
中,所以我们就不用关心多线程的问题stopSelf
方法HandlerThread
和Handler
。在它的onCreate
方法中会创建一个HandlerThread
对象,然后使用该对象的Looper
构造一个Handler
, 由这个Handler
来处理消息,由于这个Handler
是由HandlerThread
的Looper
构造的,而HandlerThread
本质上来讲是一个子线程,因此IntentService是可以执行后台作务.onHandleIntent
方法一个Demo
执行结果
由此可以看出IntentService中的任务是依次排队执行。
线程池
为什么使用线程池:
ThreadPoolExecutor
提供了一系列的参数来配置线程池,从而可以获得不同类型的线程池。当我们在创建一个线程池时,可以采用
Executors.newCachedThreadPool()
或Executors.newFixedThreadPool(5)
等方式来创建不同的线程池,但是这些方法最终都会调用ThreadPoolExecutor
来进行配置。ThreadPoolExecutor
常用的构造方法关于参数,注释中已经有了,特别说明一点。第一个参数
corePoolSize
指的是线程池中核心线程的数量。第二个参数maximumPoolSize
是线程池中最大的线程数。ThreadPoolExecutor
在执行时的特点:执行结果:
3.如果步骤2中无法将任务插入到队列中,这往往是由于任务队列已满,这个时候如果线程数量未达到线程池规定的最大值,会立即启动一个非核心线程来执行任务。如果达到了,就拒绝执行此任务[这一句没有理解?]。
线程池的分类
一种线程数量固定的线程池,当里面的线程处于空闲状态时,它们也不会被回收,除非线程池关闭了。它只有核心线程
一种线程数量不定的线程池, 它只有非核心线程,它的空闲线程有超时机制,超时时间为60s, 适合执行大量耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会因超时而被停止,此时就几乎不占系统资源。
核心线程固定,非核心线程没有限制。用于执行定时任务或具有周期性的重复任务。 如
只有一个线程的线程池,可以统一外部的任务到一个线程中,任务间不需要处理线程同步的问题。
消息机制
Android UI操作的单线程模型: 之所以对UI操作采用单线程模型,是因为如是不这样做,对UI控件的操作肯定要加锁的机制,如果这样,就使得操作UI更加的复杂,同时也降低UI的访问效率,因为锁机制会有线程的阻塞。
Android 中的消息机制,实际上就是指的
Handler
的运行机制。Handler
的运行离不开Looper
和MessageQueue
,Looper
会不断的去查找MessageQueue
中有没有新的消息,如果有就会去处理。Handler的使用
场景:在子线程中访问网络,拿到数据后更新UI。
由于
Handler
实例的构造是和当前线程绑定的,此处的new MyHandler
发生在UI线程,因此后面的handleMessage
便也是发生在UI线程.如果handler是在UI线程中初始化的,执行其post方法,最终参数Runnable会运行在UI线程,因此上面的更新UI我们也可以这么做
关于内存泄露的问题
上面的写法
MyHandler
是作为Activity的成员内部类的方式存在的。由于Java中非静态内部类会持有外部类的引用(相当于是需要一个上下文),因此需要将MyHandler
生名成静态内部类,同时持有外层Activity
的弱引用,具体的细节这里不写了,可以参看这里 #17