概述
1, 进程和线程
通俗的讲, 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
1,进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
2,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制的产生,并且线程的创建和销毁都会有相应的开销,当系统中存在大量的线程时,系统会通过时间陪轮转的方式调度每个线程,在这么多线程中有一个被称为主线程,主线程是指进程所拥有的线程。
2, Android中的线程
Android的线程也分为主线程和子线程,其中主线程又叫UI线程。在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity、BroadcastReceiver、Service)都会在同一个进程(Process)里执行,且由此进程的主线程负责执行。如果有特别指定(通过android:process),也可以让特定组件在不同的进程中运行。无论组件在哪一个进程中运行,默认情况下,他们都由此进程的主线程负责执行。
子线程
主线程主要处理界面交互相关的逻辑,主要是处理Activity组件的UI事件,Service后台服务工作。因为用户随时会和界面发生交互,因此主线程在任何时候都必须有比较高的响应速度,否则就会产生一种界面卡顿的感觉。
为了保持较高的响应速度,这就要求主线程中不能执行耗时的任务,这个时候子线程就派上用场了, 除了主线程以外的线程都是子线程。子线程主要是是执行耗时任务,比如网络请求,I/O操作等。
Android apk至少有三个线程,
1,ActivityThread创建的ApplicationThread(AMS远程调用)
2,activity 创建 ViewRoot.W
3,UI主线程
再说一次,
自定义Thread和UI线程的区别在于,UI线程是从ActivityThread运行的,在该类中的main()方法中,已经使用Looper.prepareMainLooper()为该线程添加了Looper对象,即已经为该线程创建了消息队列(MessageQueue),因此,程序员才可以在Activity中定义Hander对象(因为声明Hander对象时,所在的线程必须已经创建了MessageQueue)。而普通的自定义Thread是一个裸线程,因此,不能直接在Thread中定义Hander对象,从使用场景的角度讲,即不能直接给Thread对象发消息,但却可以给UI线程发消息。
3,ANR
Android希望UI线程能根据用户的要求做出快速响应,如果UI线程花太多时间处理后台的工作,当UI事件发生时,让用户等待时间超过5秒而未处理,Android系统就会给用户显示ANR提示信息。主线程除了处理UI事件之外,还要处理Broadcast消息。所以在BroadcastReceiver的onReceive()函数中,不宜占用太长的时间,否则导致主线程无法处理其它的Broadcast消息或UI事件。如果占用时间超过10秒, Android系统就会给用户显示ANR提示信息。解决办法自然还是解放UI主线程,将耗时操作交给子线程,避免阻塞。
4, 子线程与主线程通信
因为UI访问是没有加锁的,在多个线程中访问UI是不安全的,如果有多个子线程都去更新UI,会导致界面不断改变而混乱不堪。所以最好的解决办法就是只有一个线程有更新UI的权限,所以最合适的人选只能是主线程。
1,handler
2,AsyncTask
3,Activity.runOnUIThread(Runnable)
4,View.Post(Runnable)和View.PostDelayed(Runnabe,long)
其实后面三种方法也是对handler的一个包装,前面2中方法就不多说了,平常也用的最多。
4.1 runOnUIThread
应用举例,在子线程中,
runOnUiThread(new Runnable() {
public void run() {
•••
}
});
Acitivty中的runOnUiThread方法如下,
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);// 如果当前线程是子线程
} else {
action.run(); // 当前线程为主线程
}
}
runOnUiThread方法原理很简单了,也是通过handler方法来实现。
4.2 Post
View 的Post方法如下,
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
View 的postDelayed方法如下,
public boolean postDelayed(Runnable action, long delayMillis) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.postDelayed(action, delayMillis);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
return true;
}
5,小结
这几种方法各有优点。但是究其根本,其实后面几种方法都是对handler方法的包装,都是将message发送到UI线程的消息队列进行处理。
最后
以上就是超级跳跳糖为你收集整理的子线程与主线程之间的通信的全部内容,希望文章能够帮你解决子线程与主线程之间的通信所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复