Android多线程之常见的线程形态

作者: AntDream | 来源:发表于2018-07-16 09:59 被阅读31次

    Android 多线程系列

    Andorid中的线程除了传统的Thread外,主要还有AsyncTask、HandlerThread、IntentService。

    AsyncTask

    AsyncTask是一种轻量的异步任务类,不仅可以在后台执行任务,还能把执行的进度和最终的结果传递给UI线程以便更新UI。AsyncTask底层是封装了Thread和Handler。AsyncTask不适合执行特别耗时的任务,这种情况下还是推荐用线程池来处理

    • 四个核心方法

      • onPreExecute:在主线程中执行,在异步任务执行之前执行,可以做一些准备工作
      • doInBackground:在线程池中执行,执行具体的异步任务。在这个方法中可以调用publishProgress方法来更新任务的进度
      • onProgressUpdate:在主线程中执行,调用publishProgress方法后会被调用
      • onPostExecute:在主线程中执行,异步任务执行完毕后会被调用,返回执行结果
      • onCancelled:在主线程中执行,异步任务被取消时会被调用,这样onPostExecute方法将不会被调用
    • AsyncTask必须在主线程中加载,这意味着第一次访问AsyncTask必须发生在主线程。Android4.1及以上的版本中已经在ActivityThread的main方法中自动完成了

    • AsyncTask对象必须在主线程中创建

    • AsyncTask的execute方法必须在UI线程调用

    • 不要在程序中直接调用onPreExecute、doInBackground、onProgressUpdate、onPostExecute方法

    • 一个AsyncTask对象只能执行一次,只能调用一次execute方法,否则会报IllegalStateException异常

    • 默认情况下AsyncTask是串行执行的

    HandlerThread

    • HandlerThread继承自Thread
    public class HandlerThread extends Thread {
        int mPriority;
        int mTid = -1;
        Looper mLooper;
    
        //构造方法需要传入线程的名字
        public HandlerThread(String name) {
            super(name);
            mPriority = Process.THREAD_PRIORITY_DEFAULT;
        }
        
        public HandlerThread(String name, int priority) {
            super(name);
            mPriority = priority;
        }
        
        //用来重写,在开启消息循环之前被调用
        protected void onLooperPrepared() {
        }
    
        //主要的地方在这个run方法
        @Override
        public void run() {
            mTid = Process.myTid();
            //创建消息队列
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            //开启消息循环
            Looper.loop();
            mTid = -1;
        }
        
        public Looper getLooper() {
            if (!isAlive()) {
                return null;
            }
            
            // If the thread has been started, wait until the looper has been created.
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    
        //用于停止消息循环
        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
        //用于停止消息循环
        public boolean quitSafely() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quitSafely();
                return true;
            }
            return false;
        }
    
        public int getThreadId() {
            return mTid;
        }
    
    • HandlerThread与普通的Thread不同的地方在于它在run方法中开启了消息循环,外界需要通过Handler的消息的方式来通知HandlerThread执行一个具体的任务
    • 由于HandlerThread的run方法是一个无限循环,因此当不需要再使用HandlerThread时,可以通过quit和quitSafely方法来终止线程的执行

    IntentService

    • IntentService 是一个抽象类,所以必须创建它的子类才能使用IntentService
    • IntentService继承自Service,因此是一种特殊的服务,优先级比普通的后台线程要高,不容易被回收,适合执行一些高优先级的后台任务
    • IntentService封装了HandlerThread和Handler
    public abstract class IntentService extends Service {
        private volatile Looper mServiceLooper;
        private volatile ServiceHandler mServiceHandler;
        private String mName;
        private boolean mRedelivery;
    
        //自定义的Handler,这样可以把收到的任务消息发送给HandlerThread处理
        private final class ServiceHandler extends Handler {
            public ServiceHandler(Looper looper) {
                super(looper);
            }
    
            @Override
            public void handleMessage(Message msg) {
                //onHandleIntent处理具体的任务,运行在HandlerThread中
                onHandleIntent((Intent)msg.obj);
                //任务执行完毕会自动结束
                stopSelf(msg.arg1);
            }
        }
    
        public IntentService(String name) {
            super();
            mName = name;
        }
    
        public void setIntentRedelivery(boolean enabled) {
            mRedelivery = enabled;
        }
    
        //第一次启动时会调用onCreate
        @Override
        public void onCreate() {
            super.onCreate();
            //创建HandlerThread
            HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
            //调用HandlerThread的run方法,开启HandlerThread的消息循环,以便接收消息处理具体的任务
            thread.start();
            
            //获取HandlerThread的looper,创建ServiceHandler,这样通过ServiceHandler发送的消息最后都会在HandlerThread中处理
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
    
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = startId;
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
    
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            //每次调用IntentService都会执行onStartCommand方法,发送一个任务消息给HandlerThread处理,任务的信息通过Intent传递
            onStart(intent, startId);
            return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
        }
    
        @Override
        public void onDestroy() {
            mServiceLooper.quit();
        }
    
        @Override
        @Nullable
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @WorkerThread
        protected abstract void onHandleIntent(@Nullable Intent intent);
    }
    
    • IntentService通过Intent来传递任务参数,当任务执行完毕时会调用stopSelf(int startId)自己停止服务
    • IntentService的onHandleIntent是一个抽象方法,需要我们自己实现,用于处理具体的任务。
    • 每执行一个后台任务就需要启动一次IntentService,IntentService内部通过消息的方式向HanderThread请求执行任务,Handler的Looper是顺序执行任务的,所以IntentService也是顺序执行后台任务的。

    欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!


    AntDream

    相关文章

      网友评论

        本文标题:Android多线程之常见的线程形态

        本文链接:https://www.haomeiwen.com/subject/rmpvpftx.html