Java 线程并发/ThreadLocal 用法举例
- Java
- 2017-11-30
- 135热度
- 0评论
- 一个进程包含多个线程,这些线程共享堆空间,只有栈空间是每个线程独有的。
- 局部变量存放在栈空间,成员变量存放在堆空间。
由以上两点可以推出,线程并发时,如果同时操作了成员变量,会出问题。
public class ThreadTest {
private String userName;
public void test() {
Thread t1 = new Thread() {
public void run() {
userName = "LiLei";
process(this);
}
};
Thread t2 = new Thread() {
public void run() {
userName = "HanMeiMei";
process(this);
}
};
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
private void process(Thread t) {
System.out.println(t + ": Hello, " + userName);
try {
t.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t + ": Bye, " + userName);
}
public static void main(String[] args) {
new ThreadTest().test();
}
}
输出如下:
Thread[Thread-0,5,main]: Hello, LiLei
Thread[Thread-1,5,main]: Hello, HanMeiMei
Thread[Thread-0,5,main]: Bye, HanMeiMei
Thread[Thread-1,5,main]: Bye, HanMeiMei
第一个线程,进来的是 LiLei,出去的是 HanMeiMei……(大变活人?!)肯定是有问题的。
可以通过加同步锁来解决,也可以用 ThreadLocal,让每个线程拥有一份特定成员变量的拷贝。
public class ThreadLocalTest {
private ThreadLocal<String> userNameThreadLocal = new ThreadLocal<>();
public void test() {
Thread t1 = new Thread() {
public void run() {
userNameThreadLocal.set("LiLei");
process(this);
}
};
Thread t2 = new Thread() {
public void run() {
userNameThreadLocal.set("HanMeiMei");
process(this);
}
};
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
private void process(Thread t) {
System.out.println(t + ": Hello, " + userNameThreadLocal.get());
try {
t.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t + ": Bye, " + userNameThreadLocal.get());
}
public static void main(String[] args) {
new ThreadLocalTest().test();
}
}
输出如下:
Thread[Thread-0,5,main]: Hello, LiLei
Thread[Thread-1,5,main]: Hello, HanMeiMei
Thread[Thread-0,5,main]: Bye, LiLei
Thread[Thread-1,5,main]: Bye, HanMeiMei