AsyncTask的一些问题

        最近看书《Pro Android 4》的时候,看到书里面对AsyncTask的一个介绍,里面提到了AsyncTask的性质,在不同的系统版本中,其其实不是一个并发的线程任务。为了验证上面的过程,特地在手机上测试了,对应的测试手机系统版本是4.2,。

        书中这样介绍,当两个AsyncTask执行的时候,是先执行第一个任务,然后再第一个任务结束后,再开启新的线程来执行第二个。代码和运行结果如下:

	        TestHttpTaskA ta = new TestHttpTaskA("taskA");
		ta.executeOnExecutor("");
		TestHttpTaskA tb = new TestHttpTaskA("taskB");
		tb.executeOnExecutor("");
        代码中是两个独立的AsyncTask,然后一起调用运行代码,则输出的结果是这样的:


       在输出结果中,发现,当taskA和taskB执行的时候,先同时调用了onPreExecute方法,但是接下来,就是先执行taskA,知道taskA执行完毕(onPostExecute)后,才开始执行taskB,也就是说,实际我们认为应该是并行执行的代码,却没有并行执行,而是成顺序执行,每次只开辟一个独立的线程来处理任务。

        但是,在实际的使用过程中,我们有时是希望能够实现并行执行的,这时候,我们只需要稍微修改一下代码就行。

		ExecutorService es = Executors.newCachedThreadPool();
		TestHttpTaskA ta = new TestHttpTaskA("taskA");
		ta.executeOnExecutor(es, "");
		TestHttpTaskA tb = new TestHttpTaskA("taskB");
		tb.executeOnExecutor(es, "");
      我们为两个task的执行,分配了一个独立的线程池,这样,两个任务就会再线程池中并行执行,同时,这里调用的 Executors.newCachedThreadPool()是一个没有线程池数量上限的线程池。如果要限制线程池中线程的数量,那么也可以这样: task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,"");这样就是使用一个线程池数量为5的线程池来执行。还可以 Executors.newFixedThreadPool(7)来创建一个任意大小的线程池。

     在使用线程池后,我们的两个线程就可以并行执行了,运行的结果为:

    上面就是我们运行测试的结果,那么接下来,我们将输出系统对于AsyncTask的影响。

         在DONUT版本之前,AsyncTask的执行,是顺序执行,每次只有一个线程在执行,多个任务则是顺序执行,每次开辟一个新的线程来执行任务。

        从DONUT开始到HONEYCOMB(不包括),则系统改为采用线程池来排队,从而支持多个任务并行执行,线程池的数量限制是5;

        从HONEYCOMB开始,则又改回单任务形式,则默认仍是采用一个线程来处理任务,多个任务排队的形式。但是,为了满足并行执行的需求,系统提供了executeOnExecutor的方法来适应并发的问题。


关于AsyncTask和Thread的区别

       Thread是一个非常原始的类,只有一个run()方法可用,而且一旦开始了,就没办法控制,要想中途控制线程,需要写很多控制代码再里面。而且Thread适合做一个独立的异步任务,不需要与主线程的UI交互,如果非要交互,付出的代码量和一些同步的问题都需要注意。

       AsyncTask是一个封装好的类,可以直接继承使用,而且提供了最够的控制方法以及执行期与主线程的交互。

       由于线程的开销比较大,所以在做异步操作的时候,需要尽可能的改善设计,避免使用过多的异步。如果只是简单的数据库查询,少量的I/0操作,可以考虑不适用线程来完成。同时,如果代码中与主线程的交互没有,则使用Thread而不使用AsyncTask

     AsyncTask被设计出来的目的就是为了满足Android的特殊需求:非主线程不能操作(UI)组件,所以AsyncTask扩展Thread增强了与主线程的交互的能力。如果你的应用没有与主线程交互,那么就直接使用Thread就好了。

     当有需要大量线程执行任务时,一定要创建线程池,来对线程数量控制,减少并行线程过多带来的问题。

     线程的开销是非常大的,特别是创建一个新线程,否则就不必设计线程池之类的工具了。当需要大量线程执行任务时,一定要创建线程池,无论是使用AsyncTask还是Thread,因为使用AsyncTask它内部的线程池有数量限制,可能无法满足需求;使用Thread更是要线程池来管理,避免虚拟机创建大量的线程。     对于想要立即开始执行的异步任务,要么直接使用Thread,要么单独创建线程池提供给AsyncTask。

       默认的AsyncTask不一定会立即执行你的任务,除非你提供给他一个单独的线程池。如果不与主线程交互,直接创建一个Thread就可以了,虽然创建线程开销比较大,但如果这不是批量操作就没有问题。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值