java多线程之-Threadlocal的用法

  • 作用:存放每个线程自己私有的数据。
  • 例子:

工具类

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Thread;

import java.util.Date;

/**
 *
 * @author zjq
 */
public class LocalThread_tools {
    public static ThreadLocal<Date> t1 = new ThreadLocal<Date>();
}

线程类

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Thread;

import java.util.Date;

/**
 *
 * @author zjq
 */
public class LocalThreadA extends Thread{
    
    @Override
  synchronized public void run(){
        try {
            for(int i=0;i<20;i++){
                if (LocalThread_tools.t1.get()==null) {
                    LocalThread_tools.t1.set(new Date());
                    
                }
                System.out.println("A"+LocalThread_tools.t1.get().getTime());
                Thread.sleep(100);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Thread;

import java.util.Date;

/**
 *
 * @author zjq
 */
public class LocalThreadB extends Thread {

    @Override
   synchronized public void run() {
        try {
            for (int i = 0; i < 20; i++) {
                if (LocalThread_tools.t1.get() == null) {
                    LocalThread_tools.t1.set(new Date());

                }
                System.out.println("B" + LocalThread_tools.t1.get().getTime());
                Thread.sleep(100);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        LocalThreadA a = new LocalThreadA();
        LocalThreadB b = new LocalThreadB();
        a.start(); 
        Thread.sleep(1000);
        b.start();
    }
}

  • 结果
A1543414567634
A1543414567634
B1543414568632
A1543414567634
B1543414568632
A1543414567634
B1543414568632
........

可以看到a,b线程存在隔离性。为什么呢?
我们来看看源码

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

可以看到源码里的set()方法,首先获得了当前的线程,如果没有初始化过,就调用createMap初始化。初始化过程就是调用ThreadLocalMap的一个构造方法。ThreadLocalMap是干嘛用的?在看下ThreadLocalMap的源码。

  ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

方法中会定义一个Entry数组,初始化容量为16,扩容因子为2/3,Entry作为键值对存储,当前ThreadLocal对象为key,需要存储的对象为value。这样就实现了每个线程都有一个自己的“数据仓库”来存放自己的数据。

猜你喜欢

转载自blog.csdn.net/qq_39837953/article/details/84622892