一、为什么不用线程id作为ThreadLocalMap的key
1.1、案例代码
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/21 11:50* @Description: 需求:* 如果当前线程是线程1,那么设置书名和作者分别为 三国演义 罗贯中* 如果当前线程是线程2,那么设置书名和作者分别为 西游记 吴承恩* 如果当前线程是线程3,那么设置书名和作者分别为 水浒传 施耐庵* 如果当前线程是线程4,那么设置书名和作者分别为 红楼梦 曹雪芹* 其他线程,那么设置书名和作者分别为 朝花夕拾 鲁迅* * 在多线程并发的场景下,每个线程中的变量都是互相独立的* 线程A: 设置(变量1) 获取(变量1)* 线程B: 设置(变量2) 获取(变量2)* * ThreadLocal:* 1、set():将变量绑定到当前线程中* 2、get():获取当前线程绑定的变量*/
public class SetAndGetThreadVariableDemo4MainApp {/*** 书名*/private String name;/*** 作者*/private String author;private ThreadLocal<String> threadLocal1 = new ThreadLocal<>();private ThreadLocal<String> threadLocal2 = new ThreadLocal<>();public String getName() {return threadLocal1.get();}public void setName(String name) {threadLocal1.set(name);}public String getAuthor() {return threadLocal2.get();}public void setAuthor(String author) {threadLocal2.set(author);}public static void main(String[] args) {SetAndGetThreadVariableDemo4MainApp app = new SetAndGetThreadVariableDemo4MainApp();for (int i = 1; i <= 10; i++) {new Thread(() -> {try {switch (Thread.currentThread().getName()) {case "线程1":app.setName("三国演义");app.setAuthor("罗贯中");break;case "线程2":app.setName("西游记");app.setAuthor("吴承恩");break;case "线程3":app.setName("水浒传");app.setAuthor("施耐庵");break;case "线程4":app.setName("红楼梦");app.setAuthor("曹雪芹");break;default:app.setName("朝花夕拾");app.setAuthor("鲁迅");break;}System.out.println("================================");System.out.println("当前线程:" + Thread.currentThread().getName() + ",线程id:" + Thread.currentThread().getId() + "===>书名:" + app.getName() + ",作者:" + app.getAuthor());} catch (Exception e) {e.printStackTrace();}}, "线程" + i).start();}}}
1.2、原因
如上案例所示,当一个资源类中有2个或者多个共享变量,即有多个ThreadLocal<T>时,如果使用线程id作为ThreadLocalMap的key,由于id是唯一的,往map里面put值时,相同的id,后边的值会把前边的值覆盖掉,即作者会把书名覆盖掉,那么我们再从ThreadLocalMap中取值的时候就取不到书名信息了,因此使用线程id作为ThreadLocalMap的key是不合适的。