白话threadlocal类

每一个线程Thread都是持有一个map,叫ThreadLocalMap,而ThreadLocalMap是threadlocal类的静态内部类,所以写成ThreadLocal.ThreadLocalMap


Thread源码,起初这个map是空的:

ThreadLocal.ThreadLocalMap threadLocals = null;


当我们使用threadlocal的set方法时,

在开始时线程还没有这个map,map==null,那么会给当前线程new一个threadlocalmap。


ThreadLocal源码

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

那么第二次在使用set方法时,map就不为空了。可以使用thread的threadlocalmap了。


这个threadlocalmap的键是threadlocal对象引用,值是不同threadlocal对象 对应 的值。值可以是任意类型,因为使用了泛型


可以理解每个线程拥有一个threadlocalmap,有且只有一个,且跟其他线程独立。

这个map可以有多个键,键都是不同threadlocal对象,值是不同threadlocal对象 对应 的值。


举例:你建了两个threadlocal对象。


ThreadLocal a = new ThreadLocal(); 

ThreadLocal b = new ThreadLocal(); 


a.set("hello");

b.set("world");


那么线程甲中threadlocalMap就会有两个key,key a  对应  hello,key b  对应  world

线程乙中的threadlocalMap就会有两个key,key a  对应  hello,key b  对应  world

甲和乙线程的threadlocalmap是各自拥有的


详细例子:

class Student {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public class TestThreadLocal implements Runnable {

    ThreadLocal studentLocal = new ThreadLocal();

    public static void main(String[] args) {
        TestThreadLocal t = new TestThreadLocal();
        new Thread(t, "t1").start();
        new Thread(t, "t2").start();
    }

    @Override
    public void run() {
        accessStudent();
    }

    private void accessStudent() {
        Student s = getStudent();
        Random random = new Random();
        int age = random.nextInt(100);
        System.out.println("current thread set age " + Thread.currentThread().getName()
                + ":" + age);
        s.setAge(age);
        System.out.println("current thread first get age "
                + Thread.currentThread().getName() + ":" + s.getAge());
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("current thread second get age "
                + Thread.currentThread().getName() + ":" + s.getAge());
    }

    public Student getStudent() {
        Student s = (Student) studentLocal.get();
        if (s == null) {
            s = new Student();
            studentLocal.set(s);
        }
        return s;
    }
}

current thread set age t1:5
current thread set age t2:67
current thread first get age t2:67
current thread first get age t1:5
current thread second get age t2:67

current thread second get age t1:5

总结:

ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了线程保持对象的方法和避免参数传递的方便的对象访问方式 

ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。

网上好多文章理解有误,因为每个线程拥有独立的变量,所以并不是解决共享变量同步问题!!!!!



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值