ThreadLocal原创
# ThreadLocal 简介
ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。 它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。
- 模拟一个不合实际的场景。假设银行有10000元。 张三和李四 都来取钱。 并且都能取走自己的一万元钱。不合实际,竟然可以取走两万元
class ThreadLocalTest {
private static int account = 10000;
static class Bank {
ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){//使用ThreadLocal管理这个账户余额,就可以实现不同线程访问同一变量。复制多分,各自线程维护自己的变量
public Integer initialValue(){
return account;
}
};
public int getAccount() {
return threadLocal.get();
}
public void setAccount() {
threadLocal.set(getAccount() - 1000);
}
}
//模拟一个取钱的任务
static class TaskMoney implements Runnable{
private Bank bank;
public TaskMoney(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始取钱, 余额" + bank.getAccount());
for(int i = 1; i<= 10; i++){
bank.setAccount();
System.out.println(Thread.currentThread().getName() + "账户余额" + bank.getAccount());
}
System.out.println(Thread.currentThread().getName() + "finished");
}
}
//测试
public static void main(String[] args) {
//创建模拟银行
Bank bank = new Bank();
//创建取钱任务
TaskMoney taskMoney =new TaskMoney(bank);
//开始取钱
Thread thread1 = new Thread(taskMoney);
Thread thread2 = new Thread(taskMoney);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
- 查看运行结果, 实现取走两万元
Thread-1开始取钱, 余额10000
Thread-0开始取钱, 余额10000
Thread-1账户余额9000
Thread-0账户余额9000
Thread-1账户余额8000
Thread-0账户余额8000
Thread-1账户余额7000
Thread-0账户余额7000
Thread-1账户余额6000
Thread-1账户余额5000
Thread-0账户余额6000
Thread-1账户余额4000
Thread-0账户余额5000
Thread-1账户余额3000
Thread-0账户余额4000
Thread-1账户余额2000
Thread-0账户余额3000
Thread-1账户余额1000
Thread-0账户余额2000
Thread-1账户余额0
Thread-0账户余额1000
Thread-1finished
Thread-0账户余额0
Thread-0finished
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ThreadLocal的实现原理
每个Thread的对象都有一个ThreadLocalMap,当创建一个ThreadLocal的时候,就会将该ThreadLocal对象添加到该Map中,其中键就是ThreadLocal,值可以是任意类型。在该类中,我觉得最重要的方法就是两个:set()和get()方法。当调用ThreadLocal的get()方法的时候,会先找到当前线程的ThreadLocalMap,然后再找到对应的值。set()方法也是一样。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
编辑 (opens new window)
上次更新: 2022/03/13, 21:24:24