linux异步实现原理,Android异步处理四:AsyncTask的实现原理

分析:

在分析实现流程之前,我们先了解一下AsyncTask有哪些成员变量。

privatestaticfinalintCORE_POOL_SIZE =5;//5个核心工作线程

privatestaticfinalintMAXIMUM_POOL_SIZE =128;//最多128个工作线程

privatestaticfinalintKEEP_ALIVE =1;//空闲线程的超时时间为1秒

privatestaticfinalBlockingQueue sWorkQueue =

newLinkedBlockingQueue(10);//等待队列

privatestaticfinalThreadPoolExecutorsExecutor =newThreadPoolExecutor(CORE_POOL_SIZE,

MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。

回到例子中,点击按钮之后会新建一个GetCSDNLogoTask对象:

GetCSDNLogoTask task =newGetCSDNLogoTask();

此时会调用父类AsyncTask的构造函数:

AsyncTask.java

publicAsyncTask() {

mWorker =newWorkerRunnable() {

publicResult call()throwsException {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

returndoInBackground(mParams);

}

};

mFuture =newFutureTask(mWorker) {

@Override

protectedvoiddone() {

Message message;

Result result =null;

try{

result = get();

}catch(InterruptedException e) {

Android.util.Log.w(LOG_TAG, e);

}catch(ExecutionException e) {

thrownewRuntimeException("An error occured while executing doInBackground()",

e.getCause());

}catch(CancellationException e) {

message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,

newAsyncTaskResult(AsyncTask.this, (Result[])null));

message.sendToTarget();//取消任务,发送MESSAGE_POST_CANCEL消息

return;

}catch(Throwable t) {

thrownewRuntimeException("An error occured while executing "

+"doInBackground()", t);

}

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

newAsyncTaskResult(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象

message.sendToTarget();

}

};

}

WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。

由此可知,AsyncTask在构造的时候已经定义好要异步执行的方法doInBackground(mParams)和任务状态变化后的操作(包括失败和成功)。

当创建完GetCSDNLogoTask对象后,执行

task.execute("http://www.linuxidc.com/pic/logo.gif");

此时会调用AsyncTask的execute(Params...params)方法

AsyncTask.java

publicfinalAsyncTask execute(Params... params) {

if(mStatus != Status.PENDING) {

switch(mStatus) {

caseRUNNING:

thrownewIllegalStateException("Cannot execute task:"

+" the taskis already running.");

caseFINISHED:

thrownewIllegalStateException("Cannot execute task:"

+" the taskhas already been executed "

+"(a task canbe executed only once)");

}

}

mStatus = Status.RUNNING;

onPreExecute();//运行在ui线程,在提交任务到线程池之前执行

mWorker.mParams = params;

sExecutor.execute(mFuture);//提交任务到线程池

returnthis;

}

当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。

前面我们说到,当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。在《Android异步处理三:Handler+Looper+MessageQueue深入详解》一文中我们提到,Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:

AsyncTask.java

privatestaticclassInternalHandlerextendsHandler {

@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})

@Override

publicvoidhandleMessage(Message msg) {

AsyncTaskResult result =(AsyncTaskResult) msg.obj;

switch(msg.what) {

caseMESSAGE_POST_RESULT:

// There is onlyone result

result.mTask.finish(result.mData[0]);//执行任务成功

break;

caseMESSAGE_POST_PROGRESS:

result.mTask.onProgressUpdate(result.mData);//进度更新

break;

caseMESSAGE_POST_CANCEL:

result.mTask.onCancelled();//取消任务

break;

}

}

}

当接收到消息之后,AsyncTask会调用自身相应的回调方法。

总结:

1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。

2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务

3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数0b1331709591d260c1c78e86d0c51c18.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505680.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ue4集合类型_UE4项目问题集合

debugeditor模式下,在LoadPackage过程中crash,vs报出Stack overflow的错误这是由于Package层数过多,vs栈不够用导致的。而ue4用UBT导致不能直接修改项目的栈大小。之前项目后期就因为这个崩溃导致大家没法再用debug模式进行开发。直接的解决办…

mysql5.7 for linux7,大道浮屠诀---mysql5.7.28 for linux安装

环境:redhat6.5安装RMP包的具体操作如下:1、如有mariadb,先卸载rpm -qa |grep mariadbrpm -qa |grep mysql*rpm -e --nodeps xxxxxx (卸载查询到的rpm包)2、安装新的mysql5.7.28,解压安装包tar -xvf mysql-5.7.28-1.el6.x86_64.rpm-bundle.t…

python中提供怎样的内置库、可以用来创建用户界面_使用外部GUI库在Autodesk中创建用户界面可能会...

我不确定这是否有关联,但一些谷歌搜索发现PyQt在玛雅内部非常流行。您可以尝试使用here或here(用源代码解释了here)通过Maya创建一个新的线程循环并在其中执行。似乎Maya包含了一个模块,用于设置新的线程对象,其中包含一个QApplication&#…

做raid会损坏linux文件吗,如何从损坏的RAID系统挂载磁盘?

我有一个可怕的情况,我必须在救援的Debian Linux中从损坏的RAID系统中恢复数据。我只想以只读方式将它们全部挂载到/ mnt / rescue,以便能够将VMWare GSX映像复制到另一台计算机上,并稍后将它们迁移到ESXi。相关命令的输出如下。fdisk -lDisk…

flutter字体不跟随系统_Flutter自定义字体无法加载

SOLVED :我仍然不确定问题是什么,但我通过简单地创建一个新的Flutter项目,在新项目中设置字体,然后将我的.dart文件粘贴到新项目中来修复它 . 即使一切都完全相同(据我所知),它运作良好 . 去搞清楚 .我试图在我的应用程…

c语言求乘法,急!!!!c语言:求n次多项式的加法和乘法

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼if(s->data.coef!0.0){s->data.expnp->data.expn;r->nexts;rs;}pp->next;qq->next;break;case 1:s->data.coefq->data.coef;s->data.expnq->data.expn;r->nexts;rs;qq->next;break;}//switch}…

一维数组kmeans聚类c语言,一维数组的 K-Means 聚类算法理解

刚看了这个算法,理解如下,放在这里,备忘,如有错误的地方,请指出,谢谢需要做聚类的数组我们称之为【源数组】需要一个分组个数K变量来标记需要分多少个组,这个数组我们称之为【聚类中心数组】及一…

ktor框架用到了netty吗_Ktor-构建异步服务器和客户端的 Kotlin 框架

软件简介Ktor 是一个使用 Kotlin 以最小的成本快速创建 Web 应用程序的框架。Ktor 是一个用于在连接系统(connected systems)中构建异步服务器和客户端的 Kotlin 框架。它由 Kotlin团队创建,因此,它充分利用了 Kotlin 的语言特性,为开发者提供…

c语言根据图片轮廓图,c语言通过opencv实现轮廓处理与切割

c语言通过opencv实现轮廓处理与切割发布时间:2020-10-14 11:00:33来源:脚本之家阅读:89作者:Farmwang注意在寻找轮廓时要选择中寻找外层轮廓RETR_EXTERNAL#include "opencv/cv.h"#include "opencv/highgui.h"…

多层协议解析 c语言,基于DPI的应用层协议书解析.doc

专业资料精心整理摘要随着互联网在中国的迅速发展,全国各大网络运营商的网络规模都在不断扩张,网络结构日渐复杂,网络业务日趋丰富,网络流量高速增长,这使得网络管理的要求和难度都大大提高。因此,网络运营…

r4900g3系统安装linux_H3C UniServer R4900 G3服务器NVMe硬盘配置阵列方法以及相关操作...

一.配置NVMe硬盘的前期准备1. 安装Intel NVMe VROC 秘钥模块,该选件全称为H3C-RS3M1NVS-Intel NVMe VROC模块是一个硬件安装到主板上的NVMe SSD VROC模块接口上。Intel NVMe VROC 秘钥模块一共有如下三个版本:标准版:支持创建RAID 0、RAID 1和…

员工任务管理系统c语言,C语言职工信息管理系统课程设计任务书.docx

C语言课程设计任务书一、题目:职工信息管理系统二、目的和要求目的:要求熟练掌握C语言的基本知识和编辑技能;基本掌握结构化程序设计的基本思路和方法。要求:设计一个职工信息管理系统,使之能提供以下功能:…

android 判断 string 是否是字母数字,Android中判断字符串中必须包含字母或者数字...

public static boolean isLetterDigit(String str){boolean isDigit false;//定义一个boolean值,用来表示是否包含数字boolean isLetter false;//定义一个boolean值,用来表示是否包含字母for(int i0 ; iif(Character.isDigit(str.charAt(i))){ //用cha…

server 群辉emby_群晖容器中搭建支持硬件编码的Emby Server教程及注意事项

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我装的ubt20,intel显卡已经GVT-t直通给群晖虚拟机,再映射给EMBY的docker了,权限什么都给了,命令测试都正常一播放就只会选择软解,CPU100%,不知道怎么回事rootd…

笛卡尔心形函数表达式_如何用几何画板画笛卡尔心形函数

七夕节是个浪漫的节日,利用几何画板这个强大的绘图软件也可以对心爱的人表示!笛卡尔心形线像极了人的一颗心,用来表达爱意再好不过了。本文我们来介绍具体步骤如下:1.新建参数。右键绘图区空白处,“新建参数”&#xf…

android 指定语言的资源,Android国际化多语言切换

最近工作中突然要求要项目进行国际化,之前没遇到过。但是也很简单呀,只需要把添加一个相应语言的的strings.xml的资源文件就好了,不是吗?这样只要切换系统语言就能切换app的文字语言了。但是由此引发了一个稍微深入一点的问题&…

plotwidget横坐标日期_plotly详解(标签)x轴日期标签、y轴百分比标签设置

在作图中,我们需要根据自己的业务来更改x轴y轴的标签。注意,坐标轴的修改已经不算做画图了,因为他不是图上的线条或轨迹(trace)了,所以用layout来设置。1>显示或者不显示坐标轴标签。fig.update_layout(xaxis dict(visible Fa…

Android 抖音爱心动画,Android实现抖音心形函数

刷抖音的时候,无意间刷到 心形函数的动画,觉得很有意思, 就简单的用Android的方式实现了一下.心形函数公式公式 :心形公式X的取值范围:[-1.81,1.81],该取值范围是保证正弦函数有效取值范围。我们可以通过参数 a 的取值, 来形成不同的心形轮廓, 进而形成动…

bch纠错码 码长8_密码学BCH纠错编码算法

1日止实验目的:通过实验熟练掌握BCH纠错编码算法,学会BCH纠错编码算法程序设计,提高C程序设计能力。实验要求:开发环境要求:软件环境:windows98/windowsXP/windows2000,C环境硬件环境:计算机(C, 512MRAM&am…

android属性动画缩放和平移同时,Android 实现属性动画平移,旋转,缩放,渐变 《H》...

以下代码直接使用点击事件调用即可平移ObjectAnimator translationX new ObjectAnimator().ofFloat(myyuan,"translationX",0,600f);ObjectAnimator translationY new ObjectAnimator().ofFloat(myyuan,"translationY",0,0);AnimatorSet animatorSet ne…