Android的主线程主要是运行四大组件以及处理其与用户的交互;而子线程用于执行耗时任务,如网络请求,I/O操作。

1.Android中的线程形态

  1. AsyncTask
    在线程池中执行后台任务,其封装了Thread和Handler,通过execute方法执行AsyncTask。关键方法:
    • onPreExecute:在执行execute方法的线程中运行,一般为主线程,用于执行在开始异步任务之前的一些准备工作。
    • doInBackground:在线程池中运行,用于执行异步任务。方法中通过publishProgress方法更新任务进度,进而调用到onProgressUpdate方法。此方法需要返回计算结果给onPostExecute。
    • onProgressUpdate:主线程中运行,异步任务更新进度时被回调。
    • onPostExecute:主线程中运行,异步任务执行完毕被回调。
    • onCancelled:主线程中运行,当异步任务被取消时被回调,此时onPostExecute不会被调用。

限制:
* AsyncTask的类必须要在主线程中加载。所以第一次访问AsyncTask时需要在主线程中进行,Android 4.1以上会自动完成这个过程,在ActivityThread的main方法中。
* AsyncTask的对象必须在主线程中创建。
* execute方法必须在UI线程调用。
* 不要直接调用AsyncTask的关键方法。
* 一个AsyncTask对象只能执行一次,即execute只能调用一次,否则会抛出异常。
* 可以通过exectueOnExecutor来指定线程池执行任务。

原理:
从execute方法开始。execute会使用默认的线程池,即SerialExecutor。一个进程中所有的AsyncTask都会在这个线程池中排队(static成员):

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();        public final AsyncTask execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }

之后调用executeOnExecutor,先执行onPreExecute方法,然后线程池开始执行:

public final AsyncTask executeOnExecutor(Executor exec,        Params... params) {    ...    mStatus = Status.RUNNING;    onPreExecute();    mWorker.mParams = params;    exec.execute(mFuture);    return this;}

SerialExecutor的实现。在实例化AsyncTask的时候,会创建一个FutureTask对象,该类是一个并发类,充当了Runnable的作用,其中会包含execute传入的参数。当线程池开始执行,首先将当前的FutureTask对象插入到任务队列中,如果当前没有正在活动的任务,则调用scheduleNext方法执行下一个任务;同时一个任务执行完毕,也会调用scheduleNext方法执行下一个任务:

private static class SerialExecutor implements Executor {    final ArrayDeque mTasks = new ArrayDeque();    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);        }    }}

scheduleNext方法则通过另一个线程池,THREAD_POOL_EXECUTOR去具体执行任务,该线程池是个并发线程池。默认情况下,AsyncTask会通过SERIAL_EXECUTOR接收Runnable,串行的每次执行一个,而具体的执行任务交由THREAD_POOL_EXECUTOR;可以让AsyncTask并发的去执行Runnable,只要在其execute方法中,直接指定THREAD_POOL_EXECUTOR这个线程池就可以了。
当任务开始执行,会调用FutureTask的run方法。在实例化AsyncTask的时候,会创建一个WorkerRunnable,同时绑定到FutureTask上,FutureTask的run方法会调用WorkerRunnable的call方法,此时doInBackground方法便会被执行:

    public AsyncTask(@Nullable Looper callbackLooper) {        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()            ? getMainHandler()            : new Handler(callbackLooper);        mWorker = new WorkerRunnable() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Result result = null;                try {                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    //noinspection unchecked                    result = doInBackground(mParams);                    Binder.flushPendingCommands();                } catch (Throwable tr) {                    mCancelled.set(true);                    throw tr;                } finally {                    postResult(result);                }                return result;            }        };        mFuture = new FutureTask(mWorker) {            ...        };    }

doInBackground执行完毕,会调用postResult发送出结果,其任务就是通过AsyncTask内部的Handler发送一个msg:

private Result postResult(Result result) {    @SuppressWarnings("unchecked")    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,            new AsyncTaskResult(this, result));    message.sendToTarget();    return result;}

该Handler在创建时,Looper指定为main looper,保证其回调发生在主线程。当任务处理完成,Handler在主线程中执行AsyncTask#finish方法,当更新进度则回调AsyncTask#onProgressUpdate方法:

    private static class InternalHandler extends Handler {        public InternalHandler(Looper looper) {            super(looper);        }        @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方法中,则根据是否AsyncTask是否被取消了,去回调onCancel或者onPostExecute:

private void finish(Result result) {    if (isCancelled()) {        onCancelled(result);    } else {        onPostExecute(result);    }    mStatus = Status.FINISHED;}
  1. HandlerThread
    继承自Thread,并在run方法中创建消息队列和开启了消息循环,之后便可直接通过该Thread创建相应的Handler去执行任务。其run方法:
@Overridepublic void run() {    mTid = Process.myTid();    Looper.prepare();    synchronized (this) {        mLooper = Looper.myLooper();        notifyAll();    }    Process.setThreadPriority(mPriority);    onLooperPrepared();    Looper.loop();    mTid = -1;}
  1. IntentService
    继承自Service,内部使用了HandlerThread和Handler来实现,任务在子线程中的串行执行。onCreate方法中创建HandlerThread的实例,并通过其Looper创建Handler:
@Overridepublic void onCreate() {    // TODO: It would be nice to have an option to hold a partial wakelock    // during processing, and to have a static startService(Context, Intent)    // method that would launch the service & hand off a wakelock.    super.onCreate();    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");    thread.start();    mServiceLooper = thread.getLooper();    mServiceHandler = new ServiceHandler(mServiceLooper);}

而Handler的具体实现,是回调onHandleIntent方法,将具体的任务实现交由其子类,任务执行完毕后调用stopSelf尝试停止service。所有任务完成后,service销毁:

private final class ServiceHandler extends Handler {    public ServiceHandler(Looper looper) {        super(looper);    }    @Override    public void handleMessage(Message msg) {        onHandleIntent((Intent)msg.obj);        stopSelf(msg.arg1);    }}

client使用时,直接startService,IntentService#onStart方法中就会通过Handler将Intent包裹为msg发出,等待Looper去执行:

@Overridepublic void onStart(@Nullable Intent intent, int startId) {    Message msg = mServiceHandler.obtainMessage();    msg.arg1 = startId;    msg.obj = intent;    mServiceHandler.sendMessage(msg);}

2.Android中的线程池

优点:

  • 重用线程池中的线程,减少创建和销毁带来的性能开销;
  • 能控制最大并发数,避免大量线程抢占资源导致阻塞;
  • 能对线程进行简单的管理,提供定时执行和间隔循环执行等功能。

Android中的线程池为接口Executor,具体实现类为ThreadPoolExecutor,通过为其配置不同的参数,可以创建不同的线程池。

  1. ThreadPoolExecutor
    常用的构造方法:
public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue workQueue,                          ThreadFactory threadFactory) {
* corePoolSize:核心线程数。默认情况下,核心线程会在线程池中一直存活,即使处于闲置状态。* maximumPoolSize:最大线程数。包括了核心线程和非核心线程。* keepAliveTime:非核心线程闲置的超时时间,超过这个时间就就会被回收。当把allowCoreThreadTimeOut设置为true,同时也会作用于核心线程的。* unit:keepAliveTime的时间单位。* workQueue:线程池中的任务队列,通过execute方法提交的Runnable会添加到这里。* threadFactory:创建线程时使用的工具类。* RejectedExecutionHandler类型的不常用参数,用于指定,当无法执行新任务时,线程池会回调该handler的rejectedExecution方法,默认实现是直接抛出一个RejectedExecutionHaException异常。

ThreadPoolExecutor执行任务的规则:
1. 如果线程池中的核心线程数未达到上限,则直接启动一个核心线程去执行;
2. 如果核心线程数已达上限,则将任务插入到队列中排队;
3. 如果队列也满了,则尝试创建非核心线程去执行;
4. 如果总的线程数已经达到了上限,此时已经无法执行任务,此时便会调用RejectedExecutionHandler#rejectedExecution方法,通知调用者。

ThreadPoolExecutor在AsyncTask中的创建示例:
```
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

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 sPoolWorkQueue =        new LinkedBlockingQueue(128);/** * An {@link Executor} that can be used to execute tasks in parallel. */public static final Executor THREAD_POOL_EXECUTOR;static {    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,            sPoolWorkQueue, sThreadFactory);    threadPoolExecutor.allowCoreThreadTimeOut(true);    THREAD_POOL_EXECUTOR = threadPoolExecutor;}```* 核心线程数为2~4个* 最大线程数为2*Cpu核心数+1* 核心线程有闲置超时* 任务队列容量为128
  1. 四类线程池
    四类线程池都是通过Executors的静态方法进行创建。
    • FixedThreadPool:具有固定的核心线程,且不会被回收,当所有的核心线程处于活跃状态,新任务则排队等待。能够更快的响应外界的需求。
    public static ExecutorService newFixedThreadPool(int nThreads) {    return new ThreadPoolExecutor(nThreads, nThreads,                                  0L, TimeUnit.MILLISECONDS,                                  new LinkedBlockingQueue());}
    • CachedThreadPool:没有核心线程,具有无限数量的非核心进程,且线程闲置超时会被回收;其任务队列相当于空集,所以不会缓存任何任务,有新任务便会马上执行。适合执行大量且耗时少的任务。同时因为闲置时线程会被回收,所以其闲置状态几乎不占用系统资源。
    public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                  60L, TimeUnit.SECONDS,                                  new SynchronousQueue());}
    • ScheduledThreadPool:具有固定数量的核心线程和无限的非核心线程,非核心线程闲置超时会被回收。用于执行定时任务和周期性任务。
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {        return new ScheduledThreadPoolExecutor(corePoolSize);    }
        // ScheduledThreadPoolExecutor.java    private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;    public ScheduledThreadPoolExecutor(int corePoolSize) {        super(corePoolSize, Integer.MAX_VALUE,              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,              new DelayedWorkQueue());    }
    • SingleThreadPool:只有一个核心线程,所有的任务按顺序执行。
    public static ExecutorService newSingleThreadExecutor() {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue()));}

更多相关文章

  1. Android(安卓)中级学习心得
  2. Android(安卓)8.0 EditText 焦点无法移动到其他控件
  3. 在Eclipse下编译Android原生APK方法
  4. 实现静默安装和卸载应用
  5. H5与android原生的JS交互
  6. 让android的webview中的按钮,触发事件,也能像原生按钮一样使用
  7. Android中的对象序列化方法
  8. Android客户端与PC服务端、android服务端通过WiFi通信
  9. android view类分析

随机推荐

  1. c语言源程序经过编译后,生成文件的后缀是
  2. c语言九九乘法表代码如何写
  3. c语言结构化程序设计的三种基本结构是什
  4. c语言如何求n个数的平均值?
  5. c语言字符常量的合法表示形式是什么
  6. c语言规定,函数返回值的类型是由什么决定
  7. unsigned int几个字节
  8. c语言如何读取txt文件内容?
  9. c语言常量的正确表示方法有哪些
  10. c语言static关键字的作用是什么