Android-多线程

我每次写博客之前都忍不住想搞搞怪,这是一种什么逻辑与心态,侏罗纪与神心态,看来我很有闷骚作家的潜力啊!思泉涌动,如浩瀚江水,如涓涓细流,哈哈!不废话了。

这里写图片描述
默认情况下 : 所有在应用中的操作都运行在UI线程(主线程)上,因此之所以出现ANR问题,根因就在于主线程中被执行了耗时操作,阻塞了主线程,使其无法及时的绘制界面和相应用户的输入事件,系统可能杀死应用程序。

*来看看官方文档:*By default, all components of the same application run in the same process and thread (called the “main” thread)

原则:只有那些必须在主线程中执行才会生效的方法,才放在主线程中【界面绘制,UI更新,控件交互】,其他的一切操作都应该分逻辑地放在一个个单独的线程中执行。尤其是耗时的操作【文件,数据库,网络,计算】,同一时间运行的线程量也得控制,因为CPU频繁切换线程也是会损失性能的。

分开描述:
1) Activity. runOnUiThread(Runnable action),这里有一个概念就是:主线程的生命周期是贯串应用程序的始终的,所有在主线程上的操作,比如runnable 类型的action 【代表会被线程执行的命令】 会在Handler的协作下被投掷post到event queue 消息 队列(MessageQueue) ,Looper负责维护,不断的查询queue,一旦发现有action,立马托付给主线程执行。
函数原型截图如下:
这里写图片描述

2) Thread / Runnable :一个异步执行单元,有自己独立的堆栈,
1. 继承Thread 类,重载run()方法
new MyThread().start();

Starts executing the active part of the class’ code. This method is called when a thread is started that has been created with a class which implements Runnable.
2. new Thread(Runnable) .start()–>implements Runnable ->重载run()接口// providing a new Thread instance with a Runnable object during its creation.
new Thread(new MyRunnable()).start();
注意:
启动线程:start;

操作系统调度,设置优先级 : setPriority(int) ;

关系:Thread implements Runnable 继承关系

编程原则:每次执行操作,调用start( )都需创建一个新的Thread线程对象,避免直接使用thread类,使用其包装类,GC频繁回收闲置的线程对象,以及OS频繁创建线程对象都是影响性能的;

参考官方文档:A Thread is a concurrent unit of execution. It has its own call stack for methods being invoked, their arguments and local variables.

3) Handler : 更细粒度地控制线程上的操作,其细粒度表现在:安装操作的执行时间,对象复用,不会担心会被GC回收,对象会一直运行,这也带来一个维护问题,需要显式终止线程对象 。
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}

// runnable被封装成了一个Message ,通过其变量callback 来保存
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
Handler机制:handler实现线程间的通信,怎么理解?默认情况下刚刚建立的线程是不会关联一个消息循环【Threads by default do not have a message loop associated with them】,也就是无法关联looper【used to run a message loop for a thread.】只有主线程,才会关联一个looper,关联一个消息队列,这也就是主线程会一直运行的原因,线程之间的通信,这个时候就需要线程能够处理来自其他线程发送过来的消息事件,通过looper添加一个消息队列MessageQueue【仅仅是一个容器】message 也是由looper来打包的dispatch【holding the list of messages to be dispatched by a Looper】而把message发送添加到队列中也是由关联looper的handler完成的,因此当需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务时,就使用Looper线程,普通线程变为循环工作的线程。
**1)**MessageQueue:通过Looper.myQueue()可以获得当前线程关联的MessageQueue
还有一个前提是当前线程必须要运行关联一个looper,不然将会抛出空指针异常【NullPointerException】
2) // sThreadLocal.get() will return null unless you’ve called prepare().
static final ThreadLocal sThreadLocal = new ThreadLocal();
在源代码中、其中threadlocal应该理解为ThreadLocalVariable,当使用ThreadLocal
维护Looper对象时,它会为每个使用该对象的线程提供一个独立的Looper副本,独立修改互不影响。
public static Looper myLooper() {
return sThreadLocal.get();
}
**3)**Looper : Looper对象的创建,会自动创建一个Message Queue!单独开线程需要你关联一个Looper对象,但是没有构造函数,提供了一个Looper .prepare( )
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

private static void prepare(boolean quitAllowed) {
//每一个线程对象只能保持一个looper对象,否则重复调用,会出现运行异常
if (sThreadLocal.get() != null) {
throw new RuntimeException(“Only one Looper may be created per thread”);
}
sThreadLocal.set(new Looper(quitAllowed));
}
同时需要调用Looper.loop(),并进入消息循环for (;;),队列运行可以接受消息了,发送消息msg.target.dispatchMessage(msg);
//以下就是一个关联Looper的线程的典型例子
* class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
*
* Looper.loop();
* }
* }
Looper. quit()可以结束looper循环
Handler.getLooper().quit();

4)系统创建的主线程关联的looper和手动创建的looper区别在于一个参数quitAllowed 是否允许消息循环退出,主线程是不允许,而手动创建looper是默认退出的。

5)发送/处理/接受/移除消息:Handler

5.1.一旦线程关联的looper初始化完成,并开始运作进入消息循环状态,则其他的线程就可以发送消息了。Handler. sendMessage(Message msg) / Handler. post(Runnable r),最终这些方法都会调用sendMessageAtTime,说白了就是把消息压进栈,所以必须保证MessageQueue的存在,所以非主线程要关联looper,否则会报运行时的错误
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + ” sendMessageAtTime() called with no mQueue”);
Log.w(“Looper”, e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}

**5.2.**Handler. handleMessage() / Handler. dispatchMessage() 后者是前者的封装
//其实就是一个优先级的执行问题
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

5.3 . 当出现public class HandlerDemo extends Activity implements Handler.Callback
public interface Callback {
public boolean handleMessage(Message msg);
}

5.4. Handler只处理自己发出的消息,实现异步处理,异步 表现在,通知消息循环
要执行一个任务(Handler1.sendMessage),并在loop到自己的时候执行该任务(Handler1.handleMessage),也就是说一个线程可以有多了handler,但是只能有一个Looper !

5.5. 构造handler对象
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
或者public Handler(Looper looper, this)

**6)**Message:存在构造函数,但只是一个空壳的声明而言,并推荐两种方式来获取message!各种重载的Message. Obtain( ) 以及Handler.obtainMessage(),本质上后者是对前者的封装。
public final Message obtainMessage()
{
return Message.obtain(this);
}
在缓存池中获取新消息实例,避免每调用一次就构造不同的对象,从而实现对象复用
几个参数:
Message .what : switch区分不同消息的标志位
Message.target : handler对象,更加说明Message有不同的发送主体Handler,能找到处理它的handler。
Message .callback : Runnable
携带数据:基本INT类型/bundle类型/obj类型arg1/ arg2/data/ obj

7) HandlerThread: extends Thread 关联looper的帮助类,可以利用它来创建循环线程【Handy class for starting a new thread that has a looper. The looper can then be
used to create handler classes. Note that start() must still be called.】自带Looper使他可以通过消息来多次重复使用当前线程,而不用像原来那样创建多个匿名线程,

**8)**AsyncTask

参考文档:
http://www.cnblogs.com/angeldevil/p/3340644.html
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
http://blog.csdn.net/kesalin/article/details/37765707
http://blog.csdn.net/qjyong/article/details/2158097
http://blog.csdn.net/lmj623565791/article/details/47079737
http://blog.csdn.net/yong199105140/article/details/8425317
截图如下:
这里写图片描述
这里写图片描述
这里写图片描述
未完待续。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值