从安卓Handler到java关键字volatile

安卓中线程间通信是通过Handler来进行的。而Handler的原理是Loop在维持一个全局静态的ThreadLocal对象,ThreadLocal对象里面通过以线程对象为key,Loop对象为值来存储每个线程自己的Loop.在每个线程new一个Handler的之前都要调用Looper.prepare();就是为了给当前线程创建自己的Loop,而在创建Handler的时候需要获取到当前线程的Loop,这就是为什么要先调用Looper.prepare()的原因。

而线程的Loop对象里面又维护一个messagequeue(这个Messagequeue里面有一个Message实例,所有的消息都是使用Message链表来存储的),每次Handler发送Message的时候都是将消息根据延迟时间的先后存入messagequeue的链表中,那消息什么时候进行处理咧?这就是为什么子线程创建Handler的时候要调用Looper.loop()的原因了,loop()函数会建立一个循环来从messagequeue中获取Message,如果没有就等待,如果有就处理。

这就是Handler实现进程间通信的原理,其实底层原理就是维持一个全局的静态队列,只不过这个静态队列中保存的是线程ID和Looper实例。也就是说每个线程如果用到Handler都需要创建一个自己的Looper对象。

既然Handler可以在多个线程中访问,这就涉及到了线程同步的问题了,源码中主要用到了volatile和synchronized,来处理线程同步问题。这里说一下volatile和synchronized的区别。

  1. volatile:相当于对对象进行原子操作,java中进程有一个主内存,每个线程还有自己的工作内存,线程自己的工作内存会保留自己要用到的变量的副本,要用到这个变量的时候都是直接去使用这个副本。而加上了volatile关键字修饰的变量,线程每次使用该变量时都是去主内存中去获取该变量的最新值,这个只能保证操作的原子性,并不能保证线程操作的顺序,所以还是会出现问题。(用volatile修饰之后并不是所有的操作都是原子性的,比如n++,n=n+1这种涉及到变量的上一次的值的操作就不是原子的了,这时候就需要加上synchronized来同步)

  2. synchronized:加锁,可以修饰类,方法,代码块,多线程访问时需要先去获取锁权限,获取到之后才能开始执行,否则就阻塞等待。能保证线程执行的顺序。

你可能感兴趣的:(Android)