多线程(四)AsyncTask原理

版权声明:转载请说明出处 https://blog.csdn.net/qq_41816123/article/details/89449819

最近听了很多情感生活方面的书,最近也在知乎上看到了很多关于渣男,舔狗的评论。观点不尽相同,有抨击的有点赞的。
个人觉得,渣男我就不评论了,那种喜欢欣赏多个小姐姐的我赞同,但是你有女朋友的时候,请你做到男朋友应有的责任,如果更喜欢另一个,就分手在去追第二个你更喜欢的。如果你真的爱你的女朋友就不会更喜欢另一个,也就是你所谓更喜欢的第二个。
舔狗,一往情深的就不多说了,祝你遇上对的人。没有尊严和底线的去舔就醒醒好吗?女孩子不是追的(是去征服她去吸引她),不然你会一直处于段位低的那个人。就算最后你感动到了她,她也同意和你在一起,但是往往这种恋爱没有你们想的那么偶像剧,这是一种病态的恋爱。双方段位的不对等,你的生活需要很多的磨合,如果真的是这样,朋友请你加油,提升自己。


目录
  1. AsyncTask的使用
  2. AsyncTask的原理
  3. 总结
1. AsyncTask的使用

使用教程算是比较详细的了AsyncTask的使用

2. AsyncTask的原理

一讲到原理,大家都知道需要看源码,这时候就要用到最常用的源码查看工具
Source Insight 4.0了
我以Android8.0的源码为例子讲解AsyncTask源码
我们先看看它的构造方法

public AsyncTask() {
	mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
	    ? getMainHandler()
	    : new Handler(callbackLooper);
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
			// 设置线程的优先级
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            // 把异步操作执行的结果发送到主线程
            return postResult(doInBackground(mParams));
        }
    };

    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
            	// 在执行完任务后检查,将没被调用的Result也一并发出
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occured while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
            	//若 发生异常,则将发出null
                postResultIfNotInvoked(null);
            }
        }
    };
}

我们在看看在activity中它的execute方法的调用的源码

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

进入到我们的下一步executeOnExecutor方法中

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;//1
    exec.execute(mFuture);

    return this;
}

从注释1我们可以看出将AsyncTask的参数传给了WorkerRunnable,从前面的构造方法中我们知道WorkerRunnable是作为参数传给了FutureTask。exec是传进来的参数是sDefaultExecute它是一个串行的线程池SerialExecutor
我们在看看下面的exec.exectue方法
在这里插入图片描述
在看看我们的sDefaultExecutor.execute(runnable);方法

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() {//0
            public void run() {
                try {
                    r.run();//1
                } finally {
                    scheduleNext();//2
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);//3
        }
    }
}

在这一段代码的注释0中会将FutureTask加入到mTasks中,不管有没有执行完成或者当前活动没有在finally中都会执行scheduleNext方法,从这个方法取出FutureTask任务并交由THREAD_POOL_EXECUTOR处理。这个后面在谈
我们在注释1看到了FutureTask的run方法回到构造方法中我们可以看到它最终会调用WorekerRunnable的call方法,前面我们看到这个call最终是被return result的,我们看看这个postResult(result)方法的代码
在这里插入图片描述
创建message,嘿嘿好的,我们先从handler开始看,再看看我们的getHandler方法
在这里插入图片描述
这个方法简单
看看我们的构造方法对mHandler做了什么。
在这里插入图片描述
在看看我们的getMainHandler方法
在这里插入图片描述
什么意思呢就是mHandler 在callbackLooper==null的时候和不在主线程的时候就给它创建一个在主线程的InternalHandler(Looper.getMainLooper()),我们在看看InternalHandler类的定义
在这里插入图片描述
直接看到switch 在接收到MESSAGE_POST_RESULT消息后调用AsyncTask的finish方法下面那个进度你懂的,我们看看finish方法代码
在这里插入图片描述
到了这一步是不是就很明朗了。如果AsyncTask任务取消了,则执行onCancelled方法
否则调用onPoastExecute方法。我们就能得到异步任务执行后的结果。


我们回过头来在看看SerialExecutor
在这里插入图片描述
是这样一个线程池,THREAD_POOL_EXECUTOR指的是threadPoolExecutor,其核心线程和线程池允许创建的最大线程数都是由cpu的核数来计算出来的,他的组赛队列是LinkedBlockingQueue容量是128
在Android3.0之前AsyncTask是并行运行的,在3.0之后是串行,它保证了一个时间段只有一个任务执行,因为线程一个一个执行不会出现超过任务数和执行饱和策略的情况,同时也是提醒我们在使用多线程和阻塞队列的时候要注意任务的数量。合理编码提高我们的代码质量。
当然在3.0之后也可以并行的线程处理。
可以调用executeOnExecutor方法传递AsyncTask.THREAD_POOL_EXECUTOR参数
当然除了并行也可以传递我们的四种线程池和自定义线程池。


3. 总结

AsyncTask的原理讲完了,多线程也讲完了,之前可能大家觉得这个多线程好像和我们Android开发关系不大,但是这次的源码讲解是不是让你有了一定的了解,多线程真的无处不在,从我们的AsyncTask源码到线程池到阻塞队列,到线程。你会发现这些其实不是特别难,好了祝你在学习的过程中,轻松又快乐。
点击关注,下次我会讲解网络编程和网络框架,下下次讲一下我们的设计模式。
奇淫巧计,为求一赞。
下面抄了我大哥的几行代码,娱乐一下。

/**
 *   ------------------------------------
 *     中国 Android 编程第三区交通委提醒您:
 *   ------------------------------------
 *
 *     风 格 千 万 种
 *     规 范 第 一 条
 *     代 码 无 注 释
 *     同 事 两 行 泪
 *
 *     注 释 千 万 种
 *     编 程 第 一 条
 *     尽 量 自 解 释
 *     删 除 无 用 功
 *
 *   -----------------------------------------------------------
 *     中国 Android 编程交通委提醒您,飙车请遵守交通规则,注意安全!
 *   -----------------------------------------------------------
 *
 *  Created by syt on 2019/04/22.
 */
/***
 * ░░░░░░░░░░░░░░░░░░░░░░░░▄░░
 * ░░░░░░░░░▐█░░░░░░░░░░░▄▀▒▌░
 * ░░░░░░░░▐▀▒█░░░░░░░░▄▀▒▒▒▐
 * ░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐
 * ░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐
 * ░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌
 * ░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒
 * ░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐
 * ░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄
 * ░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒
 * ▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒
 * 单身狗就这样默默地看着你,一句话也不说。
 */

猜你喜欢

转载自blog.csdn.net/qq_41816123/article/details/89449819
今日推荐