AsyncTask与多任务

问题由来

     之前看到一篇博文,说AsyncTask不适合运行多任务, 多个任务不会异步执行, 当时只是印象里记住了一下也不确定, 今天把代码看了看, 把原因写出来。

 

问题的代码演示

 

 1 public class AsyncTaskDemo  extends AsyncTask<String, Integer, String>{
 2     private final static String TAG = "AsyncTaskTest";
 3 
 4     @Override
 5     protected String doInBackground(String... params) {
 6         Log.v(TAG, params[0] + "=================doInBackground===================PID = " + Thread.currentThread().getId());
 7 
 8         return params[0];
 9     }  
10 
11 
12 }

 

1 // 一个按钮的onclick函数    
2 public void test(View view) {
3         Log.v("AsyncTaskTest", "CPU_COUNT = " + Runtime.getRuntime().availableProcessors());
4 
5         new AsyncTaskDemo().execute("Hello1");
6         new AsyncTaskDemo().execute("Hello2");
7         new AsyncTaskDemo().execute("Hello3");
8         new AsyncTaskDemo().execute("Hello4");
9     }
//logcat里打印出来的结果12-11 16:07:34.865    1979-1979/com.sabo.helloworld V/AsyncTaskTest﹕ CPU_COUNT = 1
12-11 16:07:34.871    1979-2102/com.sabo.helloworld V/AsyncTaskTest﹕ Hello1=================doInBackground===================PID = 161
12-11 16:07:34.872    1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello2=================doInBackground===================PID = 162
12-11 16:07:34.872    1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello3=================doInBackground===================PID = 162
12-11 16:07:34.872    1979-2103/com.sabo.helloworld V/AsyncTaskTest﹕ Hello4=================doInBackground===================PID = 162

实验大致辅证了"AsyncTask不适合运行多任务"这个推断, 另一个有趣的结果是非异步执行的时候居然可能不是在一个线程里运行的【看我上面用红色标记的部分】。

 

分析:

 

1     @MainThread
2     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
3         return executeOnExecutor(sDefaultExecutor, params);
4     }

 

    @MainThreadpublic 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);// exec  --> sDefaultExecutorreturn this;}

如果熟悉Java的并发编程的话就知道sDefaultExecutor用于将要完成的任务交给内部已经实现的线程池去执行(有兴趣的话可以去看看Doug Lea写的那本《Java并发编程》)

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;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);}}}

这里的代码就能解释为什么多个AsyncTask一起执行时序列化执行而被异步的了, 

1         new AsyncTaskDemo().execute("Hello1"); //mActive == null
2         new AsyncTaskDemo().execute("Hello2"); //mActive != null
3         new AsyncTaskDemo().execute("Hello3"); //mActive != null
4         new AsyncTaskDemo().execute("Hello4"); //mActive != null

上面红色标记的代码可以看出,只有第一个任务直接调用scheduleNext()--->THREAD_POOL_EXECUTOR.execute(mActive), 线程池直接将任务交由线程去执行,而后面几个任务先被放入ArrayDeque<Runnable> mTasks, 没有交给任何线程去执行,

每个任务执行完之后又都要运行上面绿颜色标记的scheduleNext(), 从而依次序序列化执行任务。

 

上面提到的有趣的事情,既然AsyncTask是序列化执行任务的, 那么线程池里只要一个线程就能满足要求了啊, 为什么会有两个线程。

1     private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
2     private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
3     private static final int KEEP_ALIVE = 1;
4 
5     public static final Executor THREAD_POOL_EXECUTOR
6             = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
7                     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

上面我把CPU_COUNT的值打印出来是1, 所以这里线程池的线程数就可能是[2, 3]了, 然而对于AsyncTask来说1就够了, 多余1的线程其实是没有什么帮助的。

 

P.S.

:-)第一次写博客, 加上功力又有限, 欢迎大家指正canbin.zhang#qq.com

     

转载于:https://www.cnblogs.com/sabo/p/5040685.html

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

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

相关文章

iptables简单应用

可以修改/etc/rc.d/boot.local让规则重启后也能生效&#xff0c;如&#xff1a;/sbin/iptables -F/sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT/sbin/iptables -A INPUT -i eth0 -p tcp -j DROP/sbin/iptables -A INPUT -i eth0 -p udp -j DROPiptables是一个…

linux中内部命令有哪些,linux内部命令有哪些

linux中常见的内部命令有&#xff1a;1.exit命令&#xff0c;退出当前的shell&#xff1b;2.history命令&#xff0c;显示历史执行过的命令&#xff1b;3.cd命令&#xff0c;切换当前工作目录&#xff1b;4.source命令&#xff0c;重新执行刚修改的初始化文件&#xff1b;5.ech…

使用SALT-API进入集成开发的简单样例

测试的时候&#xff0c;可以CURL -K&#xff0c;但真正作集成的时候&#xff0c;却是不可以的。 必须&#xff0c;不可以让TOKEN满天飞吧。 现在进入这个阶段了。写个样例先&#xff1a; import salt import salt.auth import salt.log import saltapiopts salt.client.LocalC…

POJ 2778

题意&#xff1a;很Uva项链题目类似。 区别&#xff1a; 1、字符串很多&#xff0c;用map hash超时&#xff0c;用Trie查找。 2、DFS判断连通&#xff0c;和并查集判连通&#xff0c;被我写错的地方时&#xff0c;查森林的时候&#xff0c;还是要Find_Set。 1 #include <ios…

linux挂载VMFS硬盘,ESX4.1挂载NFS共享存储(VMkernel)

要使用vmotion,iscsi,nfs功能&#xff0c;必须启用VMkernel端口&#xff0c;ESX 4.1默认不启用&#xff0c;ESXi 5.x默认启用。在 vCenter Server“SZVCENTER01”上调用对象“datastoreSystem-44”的“HostDatastoreSystem.CreateNasDatastore” 失败。挂载NFS存储的ESX控制台命…

Perl学习之四:语句(续)

循环控制&#xff1a;1.last 退出标签的语句块2.next 3.redo不推荐&#xff0c;循环次数不可控 4.goto不推荐。***************************************标签&#xff1a; 先定义一个 labellast|next|redo|goto label&#xff1b; last VS next 相当于C语言中的&#xff1a;las…

2017年8个最流行的Web编程趋势

互联网一直在不断的发展&#xff0c;这意味着开发人员必须及时了解当前的所有变化。人们在新闻、社交、购物到银行等各大方面都与互联网有着千丝万缕的联系。因此&#xff0c;为了满足全球数百万网络用户的需求&#xff0c;Web开发需求正在上升。Web编程趋势是在W开发的过程中不…

linux 分卷压缩到指定目录,运用在android下Linux分卷压缩与分卷解压的命令

protected static Vector execRootCmd(String paramString) {Vector localVector new Vector();try {Process localProcess Runtime.getRuntime().exec("su ");// 经过Root处理的android系统即有su命令OutputStream localOutputStream localProcess.getOutputStre…

gRPC-rs:从 C 到 Rust

介绍 在上篇文章中&#xff0c;我们讲到 TiKV 为了支持 [gRPC]&#xff0c;我们造了个轮子 [gRPC-rs]&#xff0c;这篇文章简要地介绍一下这个库。首先我们来聊聊什么是 gRPC。gRPC 是 Google 推出的基于 [HTTP2] 的开源 RPC 框架&#xff0c;希望通过它使得各种微服务之间拥有…

红帽linux无法进入tty,linux自启脚本(以及无法进入tty控制台)

1.建立需开机运行的脚本auto(可以不要后面的.sh后缀)2.放在/etc/init.d/目录下 (操作系统复制命令&#xff0c;在当前文件夹下复制sudo cp auto /etc/init.d)[可能先要对init.d取得x权限]3.赋予权限&#xff0c;在init.d文件目录下sudo chmod 775 ./auto4.执行&#xff0c;命…

【最短路】SDUT3034--炸学校

炸学校 Time Limit: 2000ms Memory limit: 65536K 有疑问&#xff1f;点这里^_^ 题目描述 “小儿么小二郎&#xff0c;背着那炸弹炸学校&#xff0c;不怕那太阳晒&#xff0c;也不怕那风雨狂。”估计这首歌我们大家都耳熟能详了。于是就有一群小学生们商量着炸学校。要把本…

管控研发部门USB设备

前提背景&#xff1a;研发部门图纸经常泄漏&#xff0c;领导说要管控USB,但是要能读&#xff0c;只限制不能写。本想大力推荐Devicelock&#xff0c;因费用原因没了后话&#xff0c;只好使用最基本的域策略进行实施.51CTOblog传图片这么麻烦&#xff0c;还是全部写文字好了。实…

linux系统编程练手项目,精选 22 个 C++ 项目,编程小白练手首选!

C/C 做为元老级的编程语言&#xff0c;任时光更迭依旧屹立不倒&#xff0c;哪怕现在煊赫一时的AI&#xff0c;其底层也是用其编写。linux那么做为新手该如何快速上手 C 呢&#xff1f;固然是敲代码啊&#xff01;一切不写代码的学编程都是瞎搞。下面为你们精选了 22 个 C 项目&…

Swift iOS : WebView缓存图片的方法

广告 Swift iOS开发小书 &#xff0c;帮你快速上手开发 www.ituring.com.cn/book/2413 正文 每次加载WebView内容&#xff0c;如果图片可以缓存的话&#xff0c;速度就会非常快。默认情况下&#xff0c;WebView自己来加载图片&#xff0c;缓存的策略也是自己定的。如想要自己缓…

linux怎么同时查看两个文件,MultiTail - 在单个Linux终端中同时监视多个文件

无论是服务器管理员还是程序员&#xff0c;我们需要参考多个日志文件来有效地排除故障任务。 为了实现这一点&#xff0c;我们必须打开&#xff0c;拖尾或更少的不同shell中的每个日志文件。 但是&#xff0c;我们可以使用传统的tail命令状尾-f在/ var / log / messages文件或尾…

新一代蓝牙5标准开启 会成为物联网的最佳选择吗

在过去&#xff0c;蓝牙在生活中最常见的应用就是键盘、鼠标、音箱和蓝牙耳机&#xff0c;这些传输对频宽要求不高&#xff0c;蓝牙技术的采用不仅节省了线材成本&#xff0c;还增加了产品的灵活性。蓝牙技术联盟(SIG)正式宣布推出新一代标准蓝牙5(Bluetooth 5)&#xff0c;其主…

今日BBC

1、随身英语 Dry January 新年戒酒一个月 link 2、地道英语 Hot potato 棘手的问题“烫手山芋” link 3、今日新闻 Brussels attacks: Belgian police arrest six suspects link The arrests were made in the Schaerbeek district. There is no word yet on the identitie…

c语言中的指针语法,C语言中指针的用法介绍

C语言中指针的用法介绍for(int i0;i{num*s;s;}return num;)这个例子中的函数 fun统计一个字符串中各个字符的 ASCII 码值之和。前面说了&#xff0c;数组的名字也是一个指针。在函数调用中&#xff0c;当把 str 作为实参传递给形参 s后&#xff0c;实际是把 str 的值传递给了 s…

实验吧 貌似有点难 伪造ip

解题链接&#xff1a; http://ctf5.shiyanbar.com/phpaudit/ 解答&#xff1a; 点击View the source code —>代码显示IP为1.1.1.1即可得到KEY—>使用modify header伪造IP—>拿到flag 相关&#xff1a; modify header我也是第一次用&#xff0c;下面附上相关说明&…

用C语言用指针怎么算通用定积分,C语言:利用指针编写程序,用梯形法计算给定的定积分实例...

题目要求利用指针编写程序&#xff0c;用梯形法计算下列公式中的定积分&#xff1a;参考代码首先说明一下指针的用处&#xff1a;因为所传递的参数均为数字&#xff0c;并不需要使用指针提高效率&#xff0c;故这里使用指针指向函数。请注意calc()函数中的这一语句&#xff1a;…