ThreadLocal使用场合:主要是解决多线程中类变量、成员变量在并发访问中产生不一致的问题。ThreadLocal特点:为每个线程中使用的类变量、成员变量创建一个类变量、成员变量的副本,每个线程在运行中都是访问自己内部的副本变量。
ThreadLocal缺点:由于每个线程都创建了一个副本,因此消耗的内存资源会比没有使用ThreadLocal要多。
案例一:多线程环境下,成员变量的变化
public class ThreadB implements Runnable{ private Integer count; private ThreadTest threadTest; public ThreadTest getThreadTest() { return threadTest; } public void setThreadTest(ThreadTest threadTest) { this.threadTest = threadTest; } @Override public void run() { Integer count = threadTest.getCount(); while(count>=0) { Integer c = count--; threadTest.setCount(c); System.out.println(Thread.currentThread().getName()+"======"+c); } } }
public class ThreadTest { private Integer count = 10;//成员变量 @Test public void test() throws InterruptedException { ThreadTest threadTest = new ThreadTest(); ThreadB threadB = new ThreadB(); threadB.setThreadTest(threadTest); Thread t1 = new Thread(threadB); t1.start(); t1.join();//join()方法的作用是t1线程执行完以后,才会执行后面的代码 Integer c = threadTest.getCount(); while (c >0) { System.out.println(Thread.currentThread().getName()+":"+c--); } } public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } }
执行结果:
Thread-0======10
Thread-0======9
Thread-0======8
Thread-0======7
Thread-0======6
Thread-0======5
Thread-0======4
Thread-0======3
Thread-0======2
Thread-0======1
Thread-0======0
由此发现 main主线程已经没有任何数据可以打印了,因为count变量已经变为0了,成员变量发生了改变。
案例二:使用ThreadLocal
public class ThreadA implements Runnable{ private ThreadLocalTest threadLocalTest; public ThreadLocalTest getThreadLocalTest() { return threadLocalTest; } public void setThreadLocalTest(ThreadLocalTest threadLocalTest) { this.threadLocalTest = threadLocalTest; } @Override public void run() { Integer count = threadLocalTest.getThreadLocal().get(); while(count>=0) { Integer c = count--; threadLocalTest.getThreadLocal().set(c); System.out.println(Thread.currentThread().getName()+"======"+ threadLocalTest.getThreadLocal().get()); } } }
public class ThreadLocalTest { private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){ protected Integer initialValue() { return 10; } };//成员变量 @Test public void test() throws InterruptedException { ThreadLocalTest threadLocalTest = new ThreadLocalTest(); ThreadA threadA = new ThreadA(); threadA.setThreadLocalTest(threadLocalTest); Thread t1 = new Thread(threadA); t1.start(); t1.join();//t1线程执行完以后,才会执行后面的代码 Integer c = threadLocalTest.getThreadLocal().get(); while (c >=0) { System.out.println(Thread.currentThread().getName()+":"+c--); } } public ThreadLocal<Integer> getThreadLocal() { return threadLocal; } public void setThreadLocal(ThreadLocal<Integer> threadLocal) { this.threadLocal = threadLocal; } }
执行结果:
Thread-0======10
Thread-0======9
Thread-0======8
Thread-0======7
Thread-0======6
Thread-0======5
Thread-0======4
Thread-0======3
Thread-0======2
Thread-0======1
Thread-0======0
main:10
main:9
main:8
main:7
main:6
main:5
main:4
main:3
main:2
main:1
main:0
Thread-0线程执行有数据打印,main主线程执行也有数据打印,互不影响,因为两个线程都是用自己内部的变量副本。