博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅析 ThreadLocal
阅读量:6284 次
发布时间:2019-06-22

本文共 3016 字,大约阅读时间需要 10 分钟。

一、ThreadLocal类说明

  ThreadLocal,很容易让人望文生义,直译"本地线程"。ThreadLocal不是一个thread,是thread的局部变量。使用ThreadLocal维护变量时,它为每个使用它的线程提供独立的线程副本,每个线程可以改变自己的副本,而不会影响到其它线程对应的副本。

  从线程的角度看,目标变量就象是线程的本地变量,这也是类名中"Local"所要表达的意思。

二、ThreadLocal常用方法

①、当前变量的初始值

  protected T initialValue() 

源码 如下,该方法是一个protected方法,显然是为了让子类覆盖而设计的。该方法是在get|set会调用,且只会被调一次。ThreadLocal缺省实现直接返回null

protected T initialValue() {        return null;    }

②、设置当前线程的线程局部变量值

  void set(T value)

③、返回当前线程的线程局部变量值

  public T get()

④、删除当前线程的线程局部变量值,节省内存的占用。

  public void remove()

三、下面我们通过一个具体例子,看看ThreadLocal的具体用法---Id生成器

id生成器

public interface Sequence {    public int getId();}public class LocalSequenceImpl implements Sequence {    private ThreadLocal
container = new ThreadLocal
() { @Override protected Integer initialValue() { return 0; }; }; @Override public int getId() { container.set(container.get() + 1); return container.get(); }}

线程

public class ThreadLocalDemo extends Thread {    private static Sequence obj;    @SuppressWarnings("static-access")    public ThreadLocalDemo(Sequence obj) {        this.obj = obj;    }    public void run() {        for (int i = 0; i < 3; i++) {            System.out.println(Thread.currentThread().getName() + " : " + obj.getId());        }    }    public static void main(String[] args) {                Sequence obj = new LocalSequenceImpl();                test(obj);    }    static void test(Sequence obj) {        ThreadLocalDemo thread1 = new ThreadLocalDemo(obj);        ThreadLocalDemo thread2 = new ThreadLocalDemo(obj);        ThreadLocalDemo thread3 = new ThreadLocalDemo(obj);        thread1.start();        thread2.start();        thread3.start();    }}

结果  : 

Thread-0 : 1Thread-1 : 1Thread-1 : 2Thread-2 : 1Thread-2 : 2Thread-2 : 3Thread-1 : 3Thread-0 : 2Thread-0 : 3

从上述结果,每个线程只会更改自己的局部变量,并没有发生互相干扰的情况。可以看出来,ThreadLocal为使用它的线程提供独立的副本。

不信?我们下面再通过一个不使用ThreadLocal来验证下。

public class SequenceImpl implements Sequence {        private static int id = 0;    @Override    public int getId() {        id = id + 1;        return id;    }}

 

 结果

Thread-0 : 2Thread-0 : 4Thread-0 : 5Thread-2 : 3Thread-2 : 6Thread-2 : 7Thread-1 : 1Thread-1 : 8Thread-1 : 9

 

 仔细观察下结果,三个线程同时访问一个局部变量id,发生了互相干扰的情况。

 

四、拓展

看下ThreadLocal源码,底层是用Map实现的。我们可以自己设计一个ThreadLocal

public class MyThreadLocal
{ private Map
container = Collections.synchronizedMap(new HashMap<>()); public void set(T value) { container.put(Thread.currentThread(), value); } public T get() { Thread currentThread = Thread.currentThread(); T value = container.get(Thread.currentThread()); if(value == null && !container.containsKey(currentThread)) { value = initialValue(); container.put(Thread.currentThread(), value); } return value; } protected T initialValue() { return null; }}

 

转载于:https://www.cnblogs.com/chenmo-xpw/p/5598736.html

你可能感兴趣的文章
BZOJ1861[Zjoi2006]书架——非旋转treap
查看>>
【转】delphi 修改代码补全的快捷键(由Ctrl+Space 改为 Ctrl + alt + Space)
查看>>
lombok安装和使用
查看>>
debian var目录
查看>>
项目功能积累
查看>>
邻接表(有向图)
查看>>
字的传送
查看>>
H3C路由交换设备配置的备份与恢复
查看>>
面试题 16:反转链表
查看>>
action类型的按钮和object按钮的用法
查看>>
并查集 4104 这是一棵树吗
查看>>
servlet流(转摘)
查看>>
Android 连接 SQL Server (jtds方式)——上
查看>>
折射向量计算(Refraction Vector Calculation)
查看>>
常见的压缩文件格式案例tarZ
查看>>
QT环境下实现UI界面的“拼图游戏”
查看>>
WIN7 64位操作系统 无法找到Access驱动
查看>>
怎样解题
查看>>
HDU - 4901 The Romantic Hero(dp)
查看>>
LightOJ - 1246 Colorful Board(DP+组合数)
查看>>