Android开发之ThreadLocal的使用

来源:互联网 发布:大数据风控平台排名 编辑:程序博客网 时间:2024/05/29 16:24

1 前言

今天在学习handler源码,发现了handlder中使用了ThreadLocal。不但如此,在开源框架EventBus中也使用了ThreadLocal,所以对这个ThreadLocal做了一个研究,这里做一个总结,为一下篇handler讲解打下基础。

2 什么是ThreadLocal

官网:实现一个线程本地的存储,也就是说,每个线程都有自己的局部变量。所有线程都共享一个ThreadLocal对象,但是每个线程在访问这些变量的时候能得到不同的值,每个线程可以更改这些变量并且不会影响其他的线程,并且支持null值。

简单来说:ThreadLocal里面存储一个变量,供多个线程来访问共享。但是每一个线程改变了这个变量并不会影响其他的线程中变量的值。这就是ThreadLocal的神奇所在,让我们赶紧来学习一下吧。

3 ThreadLocal API介绍

ThreadLocal的API很简单,常用的就4个方法,下面我们来介绍一下:

方法 介绍 get() 和set()方法配合使用获取当前线程所对应的线程局部变量。 remove() 将当前线程局部变量的值删除,目的是为了减少内存的占用,需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度 set(T value) 和get()方法配合使用,设置当前线程的线程局部变量的值。也就是说只对当前线程设置,其他线程是获取不到该值的 initialValue() 返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null

值得一提的是,在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。下面我们做一个例子来介绍一下它的使用。

4 ThreadLocal实战

下面我们做一下例子来深入理解一下:

4.1 代码

我们启用3个线程。每个线程利用for循环打印5个数据。注意,我们想要是结果是:它们之间互相不影响。代码如下

public class MainActivity extends AppCompatActivity {    private  ThreadLocal<Integer>mThreadLocal;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mThreadLocal = new ThreadLocal<Integer>(){            @Override            protected Integer initialValue() {                return 0;            }        };        MyThread myThread1 = new MyThread("线程1");        MyThread myThread2 = new MyThread("线程2");        MyThread myThread3 = new MyThread("线程3");        myThread1.start();        myThread2.start();        myThread3.start();    }    private class MyThread  extends Thread{        public MyThread(String name){            super(name);        }        @Override        public void run() {            super.run();            for(int i=0;i<5;i++){                Integer num =   mThreadLocal.get();                Log.d("mystudy",this.getName()+":"+num);                mThreadLocal.set(++num);                try {                    sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}

4.2结果


由图中可以看出,3个线程并没有相互影响,各自打印自己的。

5总结

虽然我们多个线程共享一个ThreadLocal中的变量,但是ThreadLocal会分别给每个线程一个变量的副本,导致多个线程之间互不影响。

6 结尾

好了就讲到这里吧,在技术上我依旧是个小渣渣,加油!勉励自己!

0 0
原创粉丝点击