目录
一、线程简单介绍
在Android中,线程分为主线程和子线程。
主线程一般做些UI的操作,子线程一般做些耗时操作。
在操作系统中,线程是操作系统调度的最小单元,也是一种受限的系统资源,所以线程的创建数量是存在上限的,并且线程的创建和销毁都存在系统开销,所以当程序需要频繁的创建和销毁线程是就需要考虑到线程池,线程池中存在一定数量的线程,使用线程池可以避免线程频繁创建和销毁带来的系统开销。Android线程池来源于Java,后面会讲到。
二、Java线程
Java线程详见Java之线程浅析
三、AsyncTask
AsyncTask详见Android线程之AsyncTask
四、HandlerThread
HandlerThread详见Android线程之HandlerThread浅析
五、IntentService
IntentService详见Android线程之IntentService
六、线程池
线程池详见Android之线程池的浅析
七、线程间通信方式
1、Handler
Handler是主要解决子线程中不能更新UI的方案,例如下面的用法,Handler详见Android 消息机制-Handler浅析
private Handler mhandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "[handleMessage] current thread : " + Thread.currentThread().getName());
mTv.setText((String)msg.obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv);
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "[run] current thread : " + Thread.currentThread().getName());
Message message = Message.obtain();
message.obj = "你好";
mhandler.sendMessage(message);
}
}).start();
}
2、runOnUiThread
runOnUiThread可以将线程切回到主线程中,使用方法如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv);
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "[Thread run] current thread : " + Thread.currentThread().getName());
try {
Thread.sleep(3000); //模拟线程中的耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "[runOnUiThread run] current thread : " + Thread.currentThread().getName());
mTv.setText("你好");
}
});
}
}).start();
}
runOnUiThread为什么能够达到这种效果呢?看runOnUiThread的源码发现,其实它还是使用了Handler,当当前线程不是主线程的时候,使用mHandler来讲代码逻辑切换到主线程,如果当前线程是主线程,则直接调用run方法。
@Override
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
3、view.post
view.post方法也可以将代码逻辑从子线程切换到主线程,用法如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv);
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "[Thread run] current thread : " + Thread.currentThread().getName());
try {
Thread.sleep(3000); //模拟线程中的耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
mTv.post(new Runnable() {
@Override
public void run() {
Log.i(TAG, "[view.post run] current thread : " + Thread.currentThread().getName());
mTv.setText("你好");
}
});
}
}).start();
}
那 view.post方法是怎么做到的呢?查看源码,可知它也是通过Handler来切换到主线程的。
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}