前言

先考虑一个问题,多线程的情况下,如何隔离变量,例如

1
2
3
4
5
6
7
8
9
10
11
public class Number{
private int number;

public int getNumber() {
return number;
}

public void setNumber(int number) {
this.number = number;
}
}

在两个线程同时访问同一个Number实例时,从效果来看,通过getNumber获取到的是同一个值,并且可以通过setNunber修改其他线程的值,如何做到number在线程间的隔离呢

Map

先看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Number{
private Map<Thread, Integer> numberMap;

public int getNumber() {
Thread thread = Thread.currentThread();
return numberMap.get(thread);
}

public void setNumber(int number) {
Thread thread = Thread.currentThread();
numberMap.put(thread, number);
}

//防止当前线程结束后,内存无法释放
public void remove(){
Thread thread = Thread.currentThread();
numberMap.remove(thread);
}
}

从效果来看,两个线程同时访问同一个Number实例时,通过getNumber获取的值是不一样的,并且无法通过setNunber修改其他线程的值,但是有一个问题,严格来讲,numberMap仍然是线程间持有的,线程仍然可以通过手段访问到其他线程的值甚至线程对象

ThreadLocal

先看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Number{
private ThreadLocal<Integer> threadLocal;

public int getNumber() {
return threadLocal.get();
}

public void setNumber(int number) {
threadLocal.set(number);
}

//当一个线程不再使用Number时,需要调用此方法,防止内存泄露
public void remove(){
threadLocal.remove();
}
}

ThreadLocal类的get和set方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

从ThreadLocal的get和set方法,不难看出,是使用了当前线程的一个ThreadLocalMap,number相当于是存储到了线程内部,所以ThreadLocalMap 可以实现一个隔离的效果


本站总访问量:次本站总访问数:人
本站由 Peng Tong 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。