判断线程以及looper相关

该文主要用于自我总结,提炼。语句未经斟酌,存在冗余重复等情况。各人客官可移步个人主页右下方的《原创技术博客》文集,里面是对外发布的一些技术博客。(咳咳,如果用的是移动设备,好像还没支持,只能自己找。。)
当然也可继续阅读,如若有些地方生涩难懂。那。。那就给我发私信,我整理一下。( ●▽● )

判断所在的线程是不是主线程

可以使用

  if (Looper.getMainLooper()==Looper.myLooper()){
            //是主线程
        }else {
            //不是主线程
        }

这里的Looper.getMainLooper()得到的就是主线程的Looper实例。这没有什么好说的。因为主线程的Looper在UI线程创建的时候(app启动的时候)就调用了

Looper.prepare();//初始化Looper对象
Looper.loop();//启动Looper

所以说,主线程的looper实例肯定是有的,并且已经运行了。
那么工作线程(异步线程)呢?不好意思,异步线程初始化时并没有绑定一个looper实例:

Threads by default do not have a message loop associated with them. Of course, the method works

所以如果一个工作线程没有绑定looper,那么Looper.myLooper()返回的结果将是null。如果想绑定一个looper线程,并让它运行,就需要:

new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//初始化Looper对象
                Looper.loop();//启动Looper
                //做一些线程的其他逻辑
            }
        }).start();

我们看到上面Looper.myLooper(); Looper.prepare();Looper.loop();Looper的静态方法中并没有传入指定线程,但是最终得到的就是所在线程的looper或操作所在线程的looper。这是怎么做到的呢?
这是因为在Looper内部维护了一个ThreadLocal:

public class Looper {
 
    static final ThreadLocal sThreadLocal = new ThreadLocal();
 
    public static void prepare() {
       prepare(true);
    }
 
    private static void prepare(boolean quitAllowed) {
       if (sThreadLocal.get() != null) {
           throw new RuntimeException("Only one Looper may be created per thread");
       }
       sThreadLocal.set(new Looper(quitAllowed));
    }
    ...
}

我们知道,在某一个线程调用sThreadLocal.get()时,得到的是该线程的数据的looper。前面的提到的Looper.prepare()用来在本线程生成一个looper实例在这里的源码中也体现出来了。就是new 一个looper,然后放到ThreadLocal中。并且保证了一个线程只能有一个looper实例。

todo

  • 在一个线程调用ThreadLocal的get/set方法,为什么得到的就是当前thread的值?
    1. Thread currentThread = Thread.currentThread();这样能得到当前线程的信息。
    2. 然后根据当前线程的信息去ThreadLocal中拿线程对应的值。可以将ThreadLocal理解为一块存储区,将这一大块存储区分割为多块小的存储区,每一个线程拥有一块属于自己的存储区,那么对自己的存储区操作就不会影响其他线程。对于ThreadLocal,则每一小块存储区中就保存了与特定线程关联的Looper。
  • looper的looper()方法做了什么工作?

你可能感兴趣的:(判断线程以及looper相关)