1. 一个进程包含多个线程,这些线程共享堆空间,只有栈空间是每个线程独有的。
  2. 局部变量存放在栈空间,成员变量存放在堆空间。

由以上两点可以推出,线程并发时,如果同时操作了成员变量,会出问题。

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 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