Handler的前世今生之预热篇 —— ThreadLocal

Handler是android开发中必须学而且非常重要的知识点,handler主要来处理异步通讯,而这里就会涉及到多线程异步通讯,在了解Handler前先来说一下ThreadLocal

先来创建一个ThreadLocal,根据代码来了解其存储原理:

TheadLocal<String> local = new ThreadLocal();
local.set("hello"); // 设置value
local.get();// 获取value
  1. 创建一个String泛型的Threadlocal对象
  2. 存储一个String的value到local中,而这一步内部实现为:
  public void set(T value) {
        Thread t = Thread.currentThread(); //获取当前线程 
        ThreadLocalMap map = getMap(t);// 注释1
        if (map != null)
            map.set(this, value); // 注释2
        else
            createMap(t, value); // 注释3
    }

注释1:根据当前Thread对象获取该Thread对象的成员变量,ThreadLocal.ThreadLocalMap ,默认为null;ThreadLocalMap是ThreadLocal的静态内部类是一个类似Map的数据结构key为该Threadlocal对象,value是需要存储的值;
注释2:将key为threadlocal对象value存储到Threadlocalmap而这个map的引用存在于Thread类
注释3:如果Thread类中该map还未存储过数据,创建一个ThreadLocalMap指向Thread中的map,然后将值存进去,源码如下:

 /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
  1. 获取ThreadLocal的值,其实就是先获取当前Thread的成员变量ThreadLocalMap中key为当前ThreadLocal对象所对应的value
ThreadLocal与其他同步机制的区别

ThreadLocal与普通的同步机制都是为了解决多线程访问共享资源时会产生冲突的问题,普通的同步机制是控制了线程对共享资源的访问时间而避免冲突的,他是多个线程进行通信的有效方式,而ThreadLocal则是在空间上对共享数据进行了隔离,从根本上来说,数据已经不在共享了以此避免冲突。因此两种方式是在不同的角度所实现的线程安全。当我们需要多线程之间进行通信就使用同步机制,需要隔离多个线程之间的共相冲突,就是用ThreadLocal。

总结

ThreadLocal就是了一个类似Map的数据结构key是当前ThreadLocal,value是需要存储值,当set或者init的时候,实际的通过ThreadLocal创建的副本是存储在每个线程自己的threadLocals中的;

### Java `ThreadLocal` 使用方法与最佳实践 #### 创建和初始化 `ThreadLocal` `ThreadLocal` 提供了一种机制来管理每个线程独立的变量副本。这意味着不同线程操作同一个 `ThreadLocal` 变量时不会相互影响。 ```java // 定义一个 ThreadLocal 变量 private static final ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0); ``` 此代码定义了一个名为 `threadLocalValue` 的静态 `ThreadLocal` 对象,并为其指定了初始值为零[^1]。 #### 获取和设置 `ThreadLocal` 值 一旦声明了 `ThreadLocal` 实例,就可以使用其提供的 API 来获取或更新当前线程关联的数据: ```java public void setThreadData(int value){ threadLocalValue.set(value); // 设置当前线程数据 } public int getThreadData(){ return threadLocalValue.get(); // 获取当前线程数据 } ``` 这些方法允许在线程之间隔离状态的同时保持局部性[^2]。 #### 清理资源 当不再需要访问特定于线程的信息时,应当调用 `remove()` 方法清除该信息以防止潜在内存泄漏: ```java public void cleanup() { threadLocalValue.remove(); } ``` 这一步骤对于长时间运行的应用程序尤为重要,因为未清理的 `ThreadLocal` 数据可能会占用大量堆空间并导致性能下降[^3]。 #### 结合线程池的最佳实践 考虑到线程池重用了已有的工作线程而不是每次都创建新的实例,在这种情况下应特别注意如何处理 `ThreadLocal` : - 如果可能的话,尽量避免在任务内部直接依赖 `ThreadLocal`. - 当确实需要用到它时,则应在任务结束前显式移除任何存储在其内的对象. 这样做可以确保即使是在高并发环境下也能维持良好的应用表现.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值