说完了《Java中的多线程详解》之后,今天来说一下Android中的多线程。
先来列举下Android下启用多线程的方式:
new Thread()
这个和Java中一样,继承Thread,或者实现Runnable接口,再用Runnable去实例化一个Thread对象。然后start新线程。
这种方法最简单,但是也存在一些问题。
- 这只是起动了一个新的线程,没有任务的概念,不能做状态的管理。start之后,run当中的代码就一定会执行到底,无法中途取消。
- 如果从UI线程启动,则该线程优先级默认为Default,归于default cgroup,会平等的和UI线程争夺CPU资源。
AsyncTask异步任务
- 线程优先级为background,对UI线程的执行影响极小。
- 中间流出了几处回调都给了我们机会去中断任务。
- 也存在一些问题,比如在不同的系统版本上串行与并行的执行行为不一致。
HandlerThread
- HandlerThread本质上就是一个普通Thread,只不过将Handler,Thread,Looper,MessageQueue几个概念相结合。
- 采用队列的形式,也就是串行。所以当一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
- 可以处理多任务,但是只有一个线程,所有的任务要排队挨个执行。
- HandlerThread的使用步骤:
①初始化一个HandlerThread
HandlerThread handlerThread = new HandlerThread("这里给线程起一个名字");
②启动handlerThread
handlerThread.start();
③在这个线程中创建一个handler对象
Handler handler = new Handler( myHandlerThread.getLooper() ){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
Log.d( "handler " , "消息: " + msg.what + " 线程: " + Thread.currentThread().getName() ) ;
}
};
④给HandlerThread线程发消息,启动线程,可以在UI线程,也可以在子线程中发送。
//在主线程给handler发送消息
handler.sendEmptyMessage( 1 ) ;
new Thread(new Runnable() {
@Override
public void run() {
//在子线程给handler发送数据
handler.sendEmptyMessage( 2 ) ;
}
}).start() ;
⑤使用完毕后释放资源
@Override
protected void onDestroy() {
super.onDestroy();
//释放资源
myHandlerThread.quit() ;
}
IntentService
IntentService的实质是new了一个HandlerThread来串行的处理Message Queue。只不过在所有的Message处理完毕之后,工作线程会自动结束。所以可以把IntentService看做是Service和HandlerThread的结合体,适合需要在工作线程处理UI无关任务的场景。
ThreadPoolExecutor
- HandlerThread可以处理多任务,但是是串行处理的。这里ThreadPoolExecutor可以并行处理多任务。
- 使用线程池可以避免线程的频繁创建和销毁。但同时也会让代码更加复杂,一旦出了问题,解决起来会更麻烦。