ThreadLocal和线程的普通成员变量究竟有什么区别?
2018-02-25 23:40
351 查看
问题由来:
最近在看多线程的知识,有提到ThreadLocal是一种线程局部变量,每个线程都有相对独立的变量初始化拷贝,是一种以空间换时间的做法。那么问题来了,
1. 它和在线程代码里直接写一个普通成员变量有什么区别呢?
2. 它真的能“以空间换时间”吗?
问题1的思考:
问题:它和在线程代码里直接写一个普通成员变量有什么区别呢?ThreadLocal和线程的普通成员变量都是线程安全的,我觉得这是毫无疑问的。因为每个线程都有一个threadLocals,这个里面就是一个ThreadLocalMap,而ThreadLocal对象就是map的key。
这样就可以写出非常优雅的代码了,因为传入一个外部的ThreadLocal对象,或者是线程的static对象,只要你没有对它进行过初始化,那么你通过threadLocal.get()出来的就是null。这就表明,一个threadLocal对象在其他线程里面调用了set()赋值,并不会影响到另一个线程。
话又说回来了,ThreadLocal和线程的普通成员变量到底有什么区别呢?
我的理解是,普通成员变量的初始化对这个线程本身是高度耦合的,我必须要知道这个线程是哪个,必须知道这个普通成员变量名是什么才能进行赋值。
而ThreadLocal则不需要,只需要声明好泛型的类型,定义好初始化函数,或者在自己定义的getValue方法里判断ThreadLocal.get()==null?是则调用ThreadLocal.set()方法进行初始化。
就比如这个例子:
public class MyThreadLocal { //定义了一个ThreadLocal变量,用来保存int或Integer数据 private ThreadLocal<Integer> tl = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return 0; } }; public Integer getNextNum() { //将tl的值获取后加1,并更新设置t1的值 tl.set(tl.get() + 1); return tl.get(); } }
/** * 测试线程 */ public class TestThread extends Thread { private MyThreadLocal tlt = new MyThreadLocal(); public TestThread(MyThreadLocal tlt) { this.tlt = tlt; } @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "\t" + tlt.getNextNum()); } } }
/** * ThreadLocal测试 * * @author leizhimin 2010-1-5 10:43:48 */ public class Test { public static void main(String[] args) { MyThreadLocal tlt = new MyThreadLocal(); Thread t1 = new TestThread(tlt); Thread t2 = new TestThread(tlt); Thread t3 = new TestThread(tlt); Thread t4 = new TestThread(tlt); t1.start(); t2.st b9b0 art(); t3.start(); t4.start(); } }
测试结果:
Thread-0 1 Thread-1 1 Thread-0 2 Thread-1 2 Thread-0 3 Thread-1 3 Thread-2 1 Thread-3 1 Thread-2 2 Thread-3 2 Thread-2 3 Thread-3 3
由此可见,线程的代码里根本就不需要对ThreadLocal里的变量的初始化操心,这些都可以由外部的工具类完成,而工具类里也不需要管是哪个线程调用的。
我觉得这就是ThreadLocal最强大的地方!
问题2的思考:
问题:它真的能“以空间换时间”吗?我觉得这个一空间换时间是针对使用static sycronized的变量而言的。
有的线程要用到数据库连接的condition,或者是session。这些都是线程不安全的,如果一个类只有一个全局的static变量,那么是一定要用同步来控制的。
那在高并发环境下的阻塞等待是不能容忍的。
所以使用ThreadLocal可以在每个线程都能初始化一下,就解决了异步问题。
所以我觉得ThreadLocal所说的“以空间换时间”,是针对static sycronized的方式来说的。
这就是我对ThreadLocal的思考,可能有些问题,还请高手指教。
相关文章推荐
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- 静态变量和成员变量有什么区别?应该怎么调用?
- 第2章 Java编程基础——FAQ2.13 成员变量和局部变量有什么区别?
- static全局变量与普通的全局变量有什么区别?
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- H.264中普通I帧和IDR帧究竟有什么区别
- static全局变量与普通的全局变量有什么区别
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- 静态成员变量与普通成员变量的区别
- ThreadLocal成员变量和普通的成员变量对比
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- Java千百问_06数据结构(015)_数组和普通对象的引用变量有什么区别
- static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- static全局变量与普通的全局变量有什么区别?
- 静态变量与普通成员变量区别
- JAVA线程本地变量ThreadLocal和私有变量的区别
- Static全局变量与普通的全局变量有什么区别?static函数与普通函数有什么区别?
- 笔试训练-static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
- static全局变量与普通的全局变量有什么区别