Android多线程之线程间通信详解

1 线程间的交互

如上文所述,在一个线程启动别的线程主要有new Thread().start()、Executor.execute()等方式。

那么,一个线程如何终止另一个线程呢。可以有如下两种方式。

Thread.stop(),立即让线程停止,但可能会造成一些不可预期的后果,所以已经被废弃了。

Thread.interrupt(),不强制终结线程。配合isInterrupted()判断来结束线程。

InterruptedException:我们在调用 Thread.sleep(100)时,经常会抛出InterruptedException这个异常。在某个线程进入等待状态,比如调用Thread.sleep()方法或wait()方法。如果这个时候别的线程如果调用该线程的interrupt()方法,那么这个线程就会抛出这个异常,同时重置isInterrupted()为false。所以,需要在这个异常中对线程被打断的情况做处理。

try {
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
}
try {
    wait();
} catch (InterruptedException e) {
    e.printStackTrace();
}

2 sleep()方法和wait()方法的区别。

首先一点,sleep来自Thread类,和wait来自Object类。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()或notifyAll()方法后本线程才进入对象锁定池准备

另外,面试中还会经常问到Thread.join()和Thread.yield()方法。Thread.join()是让另一个线程插在自己的前面,那个插队的线程运行完,才会运行后面的代码。Thread.yield()是暂时让出自己的时间片给相同优先级的线程。

3 多线程和内存泄漏的关系

AsyncTask是多线程的一种常用方式,但是经常有文章说AsyncTack会造成内存泄漏,让我们尽量不要使用它,原因是因为它持有Activity的引用。

其实,真正的原因并不是它持有Activity的引用,它就不会被回收。而是它不仅持有Activity的引用,而且它还一直处在任务状态中,而Activity已经被销毁了,所以造成内存泄漏。

先看一下,java的垃圾回收机制,没有GC Root直接或间接持有引用的对象,会被回收。那么,什么是GC Root呢。

1. 运行中的线程

2. 静态的对象

3. native code的引用。

所以,只要AsynTask是在Activity结束之前就完成后台线程的,就不会出现内存泄漏。多线程造成的内存泄漏,并不是AsynTask特有的。像Thread、Executor等,如果后台线程一直在运行,而没有对它进行处理,也会造成内存泄漏的。

4 Android中Hnadler的实现

Handler是负责线程间交互,另外涉及到的还有Looper,Looper中有一个loop()方法,里面最重要的方法是调用

dispatchMessage(msg),具体的实现是在Handler中,代码如下,

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

Callback就是我们自己定义的Runnable,可以看到,最终是会调用handleMessage这个方法,而这个方法在Handler中是空实现,需要我们在定义Handler的时候重写这个方法。这里就能理解为什么我们平时写Handler的时候都要重写handleMessage()方法,因为Looper会把消息传到这里。

大概逻辑我们就理解了,比如有个线程A,有个Handler是在A线程中创建的,它的Looper就是一个不断loop()的死循环,获取到的消息再分发到A线程的handleMessage()中,我们只需要重写handleMessage就可以获得其它线程发过来的消息。其它线程使用该Handler的sendMessage()发送消息时,就可以把消息发到这个线程的MessageQueue,也就是消息队列。然后Looper不断的获取消息队列的消息。不断的循环,就可以保证不断的获取其它线程传过来的消息。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值