学而实习之 不亦乐乎

Android多线程的四种方式

2022-07-05 11:48:32

Android提供了四种常用的操作多线程的方式,分别是:

  1. Handler+Thread
  2. AsyncTask
  3. ThreadPoolExecutor
  4. IntentService

一、Handler+Thread

Android主线程包含一个消息队列(MessageQueue),该消息队列里面可以存入一系列的Message或Runnable对象。通过一个Handler你可以往这个消息队列发送Message或者Runnable对象,并且处理这些对象。每次你新创建一个Handle对象,它会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列,从这时起,这个handler就会开始把Message或Runnable对象传递到消息队列中,并在它们出队列的时候执行它们。

Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,Handler把 Message压入消息队列有两类方式,Post和sendMessage:

1.Post方式:

Post允许把一个Runnable对象入队到消息队列中。它的方法有:

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
removeCallbacks(Runnable r)  //从消息队列中移除一个Runnable对象。

对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。

2.sendMessage:

sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:

sendEmptyMessage(int);
sendMessage(Message);
sendMessageAtTime(Message,long);
sendMessageDelayed(Message,long);

Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重写handleMessage()方法,用于获取工作线程传递过来的消息,此方法运行在UI线程上。Message是一个final类,所以不可被继承。

优缺点

  1. 1. Handler用法简单明了,可以将多个异步任务更新UI的代码放在一起,清晰明了
  2. 2. 处理单个异步任务代码略显多

适用范围

  1. 多个异步任务的更新UI

二、AsyncTask

AsyncTask是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。

AsyncTask通过一个阻塞队列BlockingQuery存储待执行的任务,利用静态线程池THREAD_POOL_EXECUTOR提供一定数量的线程,默认128个。在Android 3.0以前,默认采取的是并行任务执行器,3.0以后改成了默认采用串行任务执行器,通过静态串行任务执行器SERIAL_EXECUTOR控制任务串行执行,循环取出任务交给THREAD_POOL_EXECUTOR中的线程执行,执行完一个,再执行下一个。

优缺

  1. 处理单个异步任务简单,可以获取到异步任务的进度
  2. 可以通过cancel方法取消还没执行完的AsyncTask
  3. 处理多个异步任务代码显得较多

适用范

  1. 单个异步任务的处理

三、ThreadPoolExecutor

ThreadPoolExecutor提供了一组线程池,可以管理多个线程并行执行。这样一方面减少了每个并行任务独自建立线程的开销,另一方面可以管理多个并发线程的公共资源,从而提高了多线程的效率。所以ThreadPoolExecutor比较适合一组任务的执行。Executors利用工厂模式对ThreadPoolExecutor进行了封装,使用起来更加方便。

Executors提供了四种创建ExecutorService的方法,他们的使用场景如下:

  1. Executors.newFixedThreadPool()  创建一个定长的线程池,每提交一个任务就创建一个线程,直到达到池的最大长度,这时线程池会保持长度不再变化
  2. Executors.newCachedThreadPool()  创建一个可缓存的线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活的回收空闲的线程,当需要增加时,    它可以灵活的添加新的线程,而不会对池的长度作任何限制
  3. Executors.newScheduledThreadPool()  创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer
  4. Executors.newSingleThreadExecutor()  创建一个单线程化的executor,它只创建唯一的worker线程来执行任务

适用范

  1. 批处理任务

四、IntentService

IntentService继承自Service,是一个经过包装的轻量级的Service,用来接收并处理通过Intent传递的异步请求。客户端通过调用startService(Intent)启动一个IntentService,利用一个work线程依次处理顺序过来的请求,处理完成后自动结束Service。

  1. 一个可以处理异步任务的简单Service