假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html
假如没有这个ThreadLocal<int>的时候,假如Thread-0这个线程set的时候可能是1,但是get的时候有可能就会是2,取的是Thread-1的值。
形象的比喻就是现在有4个人,每个人都有属于自己的雨伞,现在到某个商场了需要寄存雨伞去买东西,那么他们会把雨伞交给一个管理员,管理员会在每把雨伞上打上一个标示,表示这是谁的雨伞,等他们出来取雨伞的时候,每个人会报自己的名字(不存在谁虚报的可能,每个人都是诚实的),那么管理员就会把属于谁的雨伞交给谁。
假如现在没有这个管理员,当四个人进商场的时候都把雨伞扔进一个容器中,当他们从卖场出来的时候就会随机的村4把雨伞中拿出一把雨伞,就有可能拿错了,这就是ThreadLocal的作用。
案例1:
1 package bhz.uts.test; 2 3 public class ThreadLocalTest { 4 5 static class ResourceClass { 6 public final static ThreadLocal<String> RESOURCE_1 =new ThreadLocal<String>(); 7 public final static ThreadLocal<String> RESOURCE_2 = new ThreadLocal<String>(); 8 9 } 10 11 static class A { 12 public void setOne(String value) { 13 ResourceClass.RESOURCE_1.set(value); 14 } 15 public void setTwo(String value) { 16 ResourceClass.RESOURCE_2.set(value); 17 } 18 } 19 20 static class B { 21 public void display() { 22 System.out.println(ResourceClass.RESOURCE_1.get()+ ":" + ResourceClass.RESOURCE_2.get()); 23 } 24 } 25 26 public static void main(String []args) { 27 final A a = new A(); 28 final B b = new B(); 29 for(int i = 0 ; i < 15 ; i ++) { 30 final String resouce1 = "线程-" + i; 31 final String resouce2 = " value = (" + i + ")"; 32 new Thread() { 33 public void run() { 34 try { 35 a.setOne(resouce1); 36 a.setTwo(resouce2); 37 b.display(); 38 }finally { 39 ResourceClass.RESOURCE_1.remove(); 40 ResourceClass.RESOURCE_2.remove(); 41 } 42 } 43 }.start(); 44 } 45 } 46 }
从上面的例子我们可以看到线程放进去的是几取出来的就是几
1 线程-2: value = (2) 2 线程-5: value = (5) 3 线程-7: value = (7) 4 线程-4: value = (4) 5 线程-0: value = (0) 6 线程-3: value = (3) 7 线程-8: value = (8) 8 线程-9: value = (9) 9 线程-1: value = (1) 10 线程-6: value = (6) 11 线程-11: value = (11) 12 线程-10: value = (10) 13 线程-12: value = (12) 14 线程-13: value = (13) 15 线程-14: value = (14)
案例二:
1 package bhz.uts.utils; 2 3 public class ThreadLocalTest { 4 5 static class ResourceClass { 6 public final static ThreadLocal<String> RESOURCE_1 =new ThreadLocal<String>(); 7 8 } 9 10 static class A { 11 public void setOne(String value) { 12 ResourceClass.RESOURCE_1.set(value); 13 } 14 15 } 16 17 static class B { 18 public void display() { 19 System.out.println(Thread.currentThread().getName() + "\t" + ResourceClass.RESOURCE_1.get()); 20 21 } 22 } 23 24 public static void main(String []args) { 25 final A a = new A(); 26 final B b = new B(); 27 for(int i = 0 ; i < 15 ; i ++) { 28 final String resouce1 = "线程" + i; 29 new Thread() { 30 public void run() { 31 try { 32 a.setOne(resouce1); 33 try { 34 Thread.sleep(1000); 35 } catch (InterruptedException e) { 36 e.printStackTrace(); 37 } 38 b.display(); 39 40 }finally { 41 ResourceClass.RESOURCE_1.remove(); 42 } 43 } 44 }.start(); 45 } 46 } 47 }
放进去的线程和取出来的是同一个
1 Thread-0 线程0 2 Thread-1 线程1 3 Thread-3 线程3 4 Thread-6 线程6 5 Thread-8 线程8 6 Thread-10 线程10 7 Thread-11 线程11 8 Thread-5 线程5 9 Thread-12 线程12 10 Thread-9 线程9 11 Thread-13 线程13 12 Thread-4 线程4 13 Thread-14 线程14 14 Thread-7 线程7 15 Thread-2 线程2
案例三:反例不用ThreadLocal的时候
1 package bhz.uts.test; 2 3 public class Bean { 4 private String id ; 5 private String name ; 6 7 public Bean() { 8 } 9 10 public Bean(String id, String name) { 11 this.id = id; 12 this.name = name; 13 } 14 15 public String getId() { 16 return id; 17 } 18 19 public void setId(String id) { 20 this.id = id; 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public void setName(String name) { 28 this.name = name; 29 } 30 31 public String showinfo() { 32 return "Bean{" + 33 "id='" + id + '\'' + 34 ", name='" + name + '\'' + 35 '}'; 36 } 37 } 38 39 /** 40 * @作者 qingrui.huang 41 * @创建日期 2018-3-20--下午8:53:26 42 * @版本 43 * @描述: 44 */
1 package bhz.uts.test; 2 3 4 5 6 7 public class ThreadLocalTest { 8 9 static class ResourceClass { 10 public final static Bean bean1=new Bean(); 11 12 } 13 14 static class A { 15 public void setOne(String value) { 16 ResourceClass.bean1.setId(value); 17 } 18 } 19 20 static class B { 21 public void display() { 22 System.out.println(Thread.currentThread().getName() + "\t" + ResourceClass.bean1.getId()); 23 24 } 25 } 26 27 public static void main(String []args) { 28 final A a = new A(); 29 final B b = new B(); 30 for(int i = 0 ; i < 10 ; i ++) { 31 final String resouce1 = "线程" + i; 32 new Thread() { 33 public void run() { 34 a.setOne(resouce1); 35 b.display(); 36 37 } 38 }.start(); 39 } 40 } 41 }
结果:
1 Thread-2 线程2 2 Thread-7 线程7 3 Thread-5 线程6 4 Thread-6 线程7 5 Thread-8 线程8 6 Thread-1 线程2 7 Thread-0 线程2 8 Thread-4 线程4 9 Thread-3 线程3 10 Thread-9 线程2
可以看出线程和取出来的线程不一样,已经乱点了。