您的位置:首页 > 移动开发 > Android开发

android 中 AsyncTask 好用背后的陷阱

2013-01-30 13:42 218 查看
Jan 30,2013

更正:下文说的所谓的对象task的执行是调用了execute方法,当使用executeOnExecutor方法传递一个excutor参数时不存在下面的问题。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------


如果你已经知道AsyncTask是使用了静态的线程池,那这篇文章已经没用了。作为初学者我只是随便写写。
但是就我所知,去搜所有的关于AsyncTask网页,几乎所有文章都会告诉你:AsyncTask不阻塞UI,AsyncTask更轻量级,不需要Handler即可操作UI view。。。
先不提handler的事。刚才在做这学期第一个编程作业,一个TCP即时通信软件。因为是400/500 level的课很多本科生没有编程基础,上课的时候Steve现场编了一段服务器的代码,用AsyncTask的doInBackground做一个永真循环来listen,publishProgress(message)给onProgressUpdate方法来在UI上展示消息,一切看上去很美。
回到家我想当然的写了另一个AsyncTask的类来作为client时发送消息给peer。
重点来了:
两个类
private class ServerTask extends AsyncTask<ServerSocket, String, Void>
private class ClientTask extends AsyncTask<String, Integer, String>

第一个在onCreate的时候实例化一个对象,启动并阻塞等待connection establish

第二个在每次点击按钮的时候实例化一个局部对象

代码并不难写,运行时问题来了:虽然logcat显示server已经启动并等待了,但是不论我怎么点击发送就是收不到消息。

稍微多加了几句debug语句,发现clientTask的对象execute成功了,但是其四个关键方法并没有被执行。

我想了一会儿,觉得会不会是因为server那儿被阻塞了,于是注释掉了accept等句子,果然clientTask的方法可以被执行了。

这时候我已经几乎确认AsyncTask这货是在用静态线程之类的东西了,因为一个阻塞另一个就不能进行很自然的想到资源的互斥访问,而被访问的共享的资源很可能是定义成静态存在于内存中的。

然后我注意到debug窗口中名为AsyncTask的线程在点击之后并没有退出,索性多点了几下,发现最多可以点出来五个线程:



也就是说这其实是一个线程池,maxsize==5

但是当我每次点击发送时这儿多出一个线程来,并不是说明线程是一个一个创建的,按照一般线程池的做法,5个线程应该是一起创建,但是只有当有任务时,某个线程才被唤醒去具体处理事务,而这儿调度策略看上去貌似是顺序调度,这也只是猜测。

有人会说,既然两个或者多个AsyncTask的对象不能同时执行,还弄什么线程池。线程池是为了一个对象内部处理多线程准备的,看他的参数列表就知道。这时线程池作为临界资源任意时刻只能有一个对象访问。

当我确定了这儿有一个静态线程池作祟,立刻搜了一下“AsyncTask+静态线程池”,于是我看到了这篇:
http://blog.csdn.net/pipisky2006/article/details/8270222 和这篇
http://blog.csdn.net/mylzc/article/details/6774131
很详细可供大家参考,实际上我还没时间仔细看,只是印证了一下我的想法。

所以回到文章开头,AsyncTask是很好用,但是灵活度不够,想要更多还是自己实现吧。

哦,至于AsyncTask为什么不需要Handler,上面文章提到了,其实内部还是用Handler做到的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ANDROID asynctask 安卓