Java笔记2.3--ThreadLocal

线程里可以使用定义在主内存里的变量。

也能通过ThreadLocal存储线程本地变量。(每一个线程有一个自己的变量,所以不存在多个线程同时对主内存中的一个变量进行访问)

用多个线程爬取不同网站,每个线程用自身的ThreadLocal来维护爬取不成功的列表。

使用ThreadLocal:

class MyThreadLocal{
    //定义一个ThreadLocal变量,用来保存当前线程私有数据
    private ThreadLocal<Integer> localVal = new ThreadLocal<Integer>(){
        protected Integer initialValue(){
            return 0;
        }
    };

    private ThreadLocal<String> curName = new ThreadLocal<String>();

    public Integer add(){
        //将值+1,并更新
        localVal.set(localVal.get() + 1);
        return localVal.get() + 1;

    }

    public String setCurName(String threadName){
        try {
            curName.set(threadName);
            return curName.get();
        }finally {
            curName.remove();
        }
    }
}

class UserLocalvALThread extends Thread{
    private MyThreadLocal localObj = new MyThreadLocal();

    public UserLocalvALThread(MyThreadLocal localObj){
        this.localObj = localObj;
    }

    public void run(){
        for (int i = 0; i < 3; ++i){
            System.out.println(localObj.add() + "\t" + localObj.setCurName(Thread.currentThread().getName()));
        }
    }
}
public class ThreadLocalDemo {
    public static void main(String[] args){
        MyThreadLocal threadLocal = new MyThreadLocal();
        Thread t1 = new UserLocalvALThread(threadLocal);
        Thread t2 = new UserLocalvALThread(threadLocal);
        Thread t3 = new UserLocalvALThread(threadLocal);
        t1.start();
        t2.start();
        t3.start();
    }
}
输出:
2	Thread-0
2	Thread-2
2	Thread-1
3	Thread-2
3	Thread-0
4	Thread-2
3	Thread-1
4	Thread-0
4	Thread-1

不用ThreadLocal:

class MyThreadLocal{
    private int test =0;
    private String testString;

    public Integer add(){
        //将值+1,并更新
        test++;
        return test;

    }

    public String setCurName(String threadName){
        testString = threadName;
        return testString;
    }
}

class UserLocalvALThread extends Thread{
    private MyThreadLocal localObj = new MyThreadLocal();

    public UserLocalvALThread(MyThreadLocal localObj){
        this.localObj = localObj;
    }

    public void run(){
        for (int i = 0; i < 3; ++i){
            System.out.println(localObj.add() + "\t" + localObj.setCurName(Thread.currentThread().getName()));
        }
    }
}
public class ThreadLocalDemo {
    public static void main(String[] args){
        MyThreadLocal threadLocal = new MyThreadLocal();
        Thread t1 = new UserLocalvALThread(threadLocal);
        Thread t2 = new UserLocalvALThread(threadLocal);
        Thread t3 = new UserLocalvALThread(threadLocal);
        t1.start();
        t2.start();
        t3.start();
    }
}
输出结果:
1	Thread-0
4	Thread-0
3	Thread-2
6	Thread-2
7	Thread-2
2	Thread-1
8	Thread-1
5	Thread-0
9	Thread-1

初始化均使用的是同一个threadLocal,使用ThreadLocal和不使用结果如上。

set方法:调用时传入一个参数,放入ThreadLocalMap对象,用当前ThreadLocal为Key,如果没有ThreadLocalMap对象,由当前线程t创建。

get方法:通过当前线程,得到所属的ThreadLocalMap,以及Entry,从Entry中获得Value。

ThreadLocalMap:通过内部的ThreadLocalMap对象来存储本地变量。

ThreadLocalMap里每个元素是Entry。

每个Entry是键值对,键是当前ThreadLocal对象,值是本地变量。

Entry是继承WeakReference,是弱引用。

一个线程类可以有多个ThreadLocal变量。(上面的就两个)

一个线程类里有一个ThreadLocalMap。

一个ThreadLocalMap里有多个Entry。

每个Entry存储了一个ThreadLocal本地变量。

在ThreadLocal里保存值时,会放入Entry对象。Entry是基于弱引用,如创建ThreadLocal的线程终止,会回收。但是如果创建ThreadLocal的线程一直运行,value就可能无法回收。所以及时remove。

 

说法总结:

1.在xx业务用到ThreadLocal保存本地变量。

2.指出内部实现是ThreadLocalMap。说明具体关系。

3.结合set,get等源码讲述赋值和取值。

4.结合Entry弱引用,讲述可能引发内存泄漏,及时remove。

5.引导到垃圾回收话题

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值