AsyncTask封装了线程池和Handler,方便用来子线程里面更新UI,HandlerThread具有消息循环的线程,可以直接在内部使用Handler,IntentService封装方便地执行后台任务,内部使用HanlderThread来执行任务。
IntentService做为一种服务,不容易被系统杀死,如果一个线程里面附加到四大组件,优先级很低,容易被系统回收,关于进程优先级可以参考官方文档Processes and Threads
前台进程 > 可见进程 > 服务进程 > 后台进程 > 空进程
AsyncTask实例(官方文档里面的):
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected void onPreExecute() {
//init
}
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
//use
new DownloadFilesTask().execute(url1, url2, url3);
AsyncTask
四个重要的方法:onPreExecute doInBackground onProgressUpdate onPostExecute,除了doInBackground是在Worker Thread里面执行的,其余的都在UI线程里面执行。
使用条件限制:
Android 1.6之前,AsyncTask是串行执行任务的,Android 1.6开始使用线程池来处理,Android 3.0之后,为了避免并发错误,又采用了串行执行任务,之后如果想要使用线程池的话可以使用executeOnExecotor,并且可以使用AsyncTask为我们准备好的线程池,AsyncTask.THREAD_POOL_EXECUTOR。
HandlerThread
HandlerThread也是一种Thread,只是里面带有Looper,可以用来创建Handler并将Looper附加在上面,这样就就可以向子线程里面发消息,执行相应的任务。
public class HanlderThread extend Thread {
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
}
简单使用:
HandlerThread thread = new HandlerThread("my");
thread.start();
Looper looper = thread.getLooper();
Handler mServiceHandler = new Handler(looper){
@Override
public void handleMessage(Message msg) {
//dosomething
}
};
mServiceHandler.sendMessage(Message.obtain());
thread.quit();
IntentService
Intent是一种抽象的Service,我们需要实现这个抽象的方法,这个就是我们需要在Worker Thread里面执行任务重写的方法:
protected abstract void onHandleIntent(Intent intent);
IntentService可用于执行耗时的任务,当任务执行结束之后会自动停止,由于是一种Service,优先级比单独的线程高,不容易被系统回收。IntentService封装了HandlerThread与Handler,从实现的onCreate可看的出来
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
启动服务的时候,会执行onStartCommand,然后使用mServiceHandler向HandlerThread发消息,mRedelivery表示Service被意外杀死后的行为,true表示START_REDELIVER_INTENT重启Service并重新发送Intent,false为START_NOT_STICKY不做任何操作,可以通过setIntentRedelivery来控制。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
ServiceHandler的实现,收到消息后调用onHandleIntent处理我们发来的请求,结束之后调用stopSelf(int startId)来尝试停止服务,注意调用stopSelf()会立刻停止服务,stopSelf(int startId)会在停止服务之前判断启动服务的次数是否和startId相等,如果相等就停止服务,这个策略是有ActivityManagerService来控制的。
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
由于使用的是Handler机制来处理,所以执行任务是串行的。
使用线程池能够对线程做管理,并且减小线程创建和销毁的开销,控制线程的并发数,避免大量线程抢占系统资源。
线程池主要使用ThreadPoolExecutor来实现,通过配置构造方法的参数来达到想要的效果:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数,核心线程默认情况下会一直存活,即使线程池处于闲置状态
maximumPoolSize:允许线程池的最大数量,达到这个值之后,后续的任务将会被阻塞
keepAliveTime:非核心线程闲置的超时时长,超过就会被回收
TimeUnit:keepAliveTime的单位
workQueue:线程池里面的任务队列
threadFactory:线程池工厂,为线程池提供创建线程的策略
handler:当线程池慢了的拒绝策略,默认的策略是抛RejectedExecutionException
ThreadPoolExecutor线程池执行任务规则:
创建线程池可以使用JDK给我们提供的Executors来创建,下面四种比较常见的线程池:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
线程数量固定的线程池,处于空闲空闲状态也不会被回收,任务队列没有大小限制。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
线程数量不定的线程池,只有非核心线程,线程数量不能大于Integer.MAX_VALUE,提交新任务就会启动新线程,空闲线程只能存活60s,任务队列相当于一个空集合,提交任何任务都会被立即执行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
核心线程固定,非核心线程没有限制的线程池,并且当非核心线程闲置时会被立即回收,主要用来执行定时任务和具有固定周期的重复任务。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
内部只有一个核心线程,确保所有任务都按照顺序在同一个线程中执行,所以任务之间不需要处理线程同步的问题。