线程是系统调度的最小单位。
Android主线程和子线程
主线程用于运行四大组件及用户的交互,
子线程用于执行耗时任务,网络请求,io操作等
AsyncTask
AsyncTask封装了线程池和Handler,是一种轻量级的异步任务类,特别耗时的任务不建议使用。有几个核心方法:
onPreExecute(),任务执行前调用在主线程执行
doInBackGround(),在子线程执行,可以在内部调用publishProgress()方法更新任务的进度调用该方法会调用onProgressUpdate()方法,在doInbackGround()中需要将结果返回
onProgressUpdate(),在主线程中执行,可以用于更新ui
onPostExcute(),得到doInBackGround的结果
onCanceled(),异步任务被取消时被调用。
调用excute()启动任务执行流程
那看看AsyncTask的excute方法源码:
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
调用了excuteOnExcutor(),跟进去看看
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
调用了Excutor的execute方法,看看
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
可以看到SerialExcutor的execute用于将任务的调度,THREAD_POOL_EXECUTOR才是执行任务的线程池,mActive是在任务队列里的Runnable对象,执行完之后如何返回结果呢
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
看构造函数中调用postResult()将结果返回
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
postResult使用handler发送了一个消息,来看看这个handler的handlemessage()处理,
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
调用了finish()
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
和onProgressUpdate()将结果返回到了ui线程处理,所以该handler必须要在主线程创建,这也要求了AsyncTask必须在ui线程创建
==使用注意事项==
1.AsyncTask必须在主线程中加载,在4.1以上版本系统已经替我们做好了,
2.对象必须在主线程中创建,
3.execute必须在主线程中执行
4.注意3.0之后AsyncTask是串行执行任务的,但可以使用executeOnexcutor()方法使用自定义的线程池用于执行任务,1.6到3.0是并行的,
HandlerThread
是个继承了Thread的内部创建了Looper和消息队列的类,所以可以在使用它来创建handler,其run方法是个死循环,需要及时使用looper.quit()退出线程。
该类用于IntentService
IntentService
IntentService是继承自Service的抽象类,用于执行后台任务,内部使用了HandlerThread,优先级比普通的线程高,不容易被系统杀死。
IntentService第一次启动时onCreate会执行创建HandlerIntent对象,以后每次启动调用onStartcommand()方法,其中将intent做为消息发送给用HandlerThread对象创建的handler,在handler的handlemessage()中调用了onhandleintent()方法,执行完所有后台任务会调用stopself(),service结束自己。
Android的线程池
线程池的作用:
重用线程池中的线程,避免因为线程的创建、销毁所带来的性能开销。
控制并发数量,避免线程之间互相抢占系统资源而导致的阻塞现象,
能够对线程进行管理,定时或延时
java的Executor为线程池类接口,实现类为threadPoolExcutor,通过配置该类的参数,Android线程池可以分为四类
构造函数
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;
}
corePoolSize:核心线程数,默认情况,核心线程会一直存活,及时他们处于闲置状态,如果allowcoreThreadtimeout设为true,那么闲置的核心线程在等待新任务到来时会有超时策略,时间超过了keepAliveTime后会终止。
maximumPoolSize:最大线程数,线程数达到最大后后续的任务会被阻塞
keepAliveTime:非核心线程的超时时长,也作用与核心线程。
unit :超时时长的单位
workQueue:线程池的任务队列,execute方法提交的runnable会存入这里。
threadFactory: 为线程池提供创建线程的功能。接口,只有newthread()方法
RejectedExecutionHandler,在无法执行新任务情况下的回调接口
线程池的调度规则
1.如果线程池的核心线程未满,则新任务会创建新县城
2.如果线程池数量已经达到或者超过核心线程,那么任务会放入任务队列等待
3.如果任务队列已满,线程数未达到最大值,会启动一个非核心线程。
4.如果任务队列已满,会执行构造函数最后一个参数的回调
来看看Android的AsyncTask线程池配置
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
四类线程池
fixedThreadPool,固定核心线程数,没有非核心,不会回收,响应速度块
CachedThreadPool,没有核心线程,任意非核心,用于处理 大量的耗时少的任务,没有线程数的限制,没有任务个数限制,超时停止
ScheduledThreadPool,固定核心,任意非核心,非核心闲置时会被回收,用于执行定时任务和固定周期的任务。
SingleThreadExcutor,只哟一个核心线程,单线程执行,不需要同步