⼀、类ThreadLocal的使⽤
变量值的共享可以使⽤public static 变量的形式,所有的线程都使⽤同⼀个public static 变量,如果想实现每⼀个线程都有⾃⼰的共享变量该如何解决ThreadLocal可以解决。
它作⽤就是每⼀个线程绑定⾃⼰的值,可以将ThreadLocal类⽐喻成全局存放数据的盒⼦,盒⼦中可以存储每⼀个线程的私有数据。
(⼀)验证线程变量的隔离性
package com.it.po.thread10;public class Tools {
public static ThreadLocal t1 =new ThreadLocal();}
package com.it.po.thread10;
public class ThreadA1 extends Thread{ @Override
public void run() { super.run(); try {
for(int i=0;i<10;i++) {
Tools.t1.set(\"ThreadA1 \" + (i + 1));
System.out.println(\"ThreadA1 get value \" + Tools.t1.get()); Thread.sleep(200);//添加完将cpu让给其他线程 }
} catch (InterruptedException e) { e.printStackTrace(); } }}
package com.it.po.thread10;
public class ThreadB1 extends Thread{ @Override
public void run() { super.run(); try {
for(int i=0;i<10;i++) {
Tools.t1.set(\"ThreadB1 \" + (i + 1));
System.out.println(\"ThreadB1 get value \" + Tools.t1.get()); Thread.sleep(200);//添加完将cpu让给其他线程 }
} catch (InterruptedException e) { e.printStackTrace(); } }}
package com.it.po.thread10;public class Run7 {
public static void main(String[] args) throws InterruptedException { ThreadA1 threadA1 = new ThreadA1(); ThreadB1 threadB1 = new ThreadB1(); threadA1.start(); threadB1.start(); for(int i=0;i<10;i++) {
Tools.t1.set(\"main \" + (i + 1));
System.out.println(\"main get value \" + Tools.t1.get()); Thread.sleep(200);//添加完将cpu让给其他线程 } }}
main get value main 1
ThreadA1 get value ThreadA1 1ThreadB1 get value ThreadB1 1ThreadA1 get value ThreadA1 2main get value main 2
ThreadB1 get value ThreadB1 2ThreadA1 get value ThreadA1 3main get value main 3
ThreadB1 get value ThreadB1 3ThreadA1 get value ThreadA1 4main get value main 4
ThreadB1 get value ThreadB1 4ThreadA1 get value ThreadA1 5main get value main 5
ThreadB1 get value ThreadB1 5ThreadA1 get value ThreadA1 6main get value main 6
ThreadB1 get value ThreadB1 6ThreadA1 get value ThreadA1 7main get value main 7
ThreadB1 get value ThreadB1 7ThreadA1 get value ThreadA1 8main get value main 8
ThreadB1 get value ThreadB1 8ThreadA1 get value ThreadA1 9main get value main 9
ThreadB1 get value ThreadB1 9ThreadA1 get value ThreadA1 10main get value main 10
ThreadB1 get value ThreadB1 10
结论:
每⼀个线程都能得到⾃⼰的数据,
ThreadLocal类解决的就是变量在不同线程之间的隔离性
(⼆)再证明数据的隔离性
package com.it.po.thread10;import java.util.Date;public class Tool2 {
public static ThreadLocal package com.it.po.thread10;import java.util.Date; public class ThreadA2 extends Thread{ @Override public void run() { super.run(); try { for(int i=0;i<10;i++) { if(Tool2.t1.get()==null){ Tool2.t1.set(new Date()); } System.out.println(\"A get value \" + Tool2.t1.get().getTime()); Thread.sleep(200);//添加完将cpu让给其他线程 } } catch (InterruptedException e) { e.printStackTrace(); } }} package com.it.po.thread10;import java.util.Date; public class ThreadB2 extends Thread{ @Override public void run() { super.run(); try { for(int i=0;i<10;i++) { if(Tool2.t1.get()==null){ Tool2.t1.set(new Date()); } System.out.println(\"B get value \" + Tool2.t1.get().getTime()); Thread.sleep(200);//添加完将cpu让给其他线程 } } catch (InterruptedException e) { e.printStackTrace(); } }} package com.it.po.thread10;public class Run8 { public static void main(String[] args) throws InterruptedException { ThreadA2 threadA2 = new ThreadA2(); ThreadB2 threadB2 = new ThreadB2(); threadA2.start(); Thread.sleep(1000);//添加完将cpu让给其他线程 threadB2.start(); }} A get value 1575130507094A get value 1575130507094A get value 1575130507094A get value 1575130507094A get value 1575130507094B get value 1575130508092A get value 1575130507094B get value 1575130508092A get value 1575130507094B get value 1575130508092A get value 1575130507094B get value 1575130508092A get value 1575130507094B get value 1575130508092A get value 1575130507094B get value 1575130508092B get value 1575130508092B get value 1575130508092B get value 1575130508092B get value 1575130508092 分析: 第⼀次调⽤ThreadLocal类返回是null,怎么解决这⼀的问题? package com.it.po.thread10; public class ThreadLocalExt extends ThreadLocal { @Override protected Object initialValue() { return \"我是默认值,第⼀次返回不再为null\"; }} package com.it.po.thread10;public class Ru9 { public static ThreadLocalExt t1 =new ThreadLocalExt(); public static void main(String[] args) throws InterruptedException { for(int i=0;i<10;i++){ if(t1.get()==null){ System.out.println(\"从未放过值\"); t1.set(\"我的值popo\"); } System.out.println(\"get value \"+t1.get()); } }} get value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为null get value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为nullget value 我是默认值,第⼀次返回不再为null (三)再证明数据的隔离性 package com.it.po.thread10;import java.util.Date; public class ThreadLocalExt extends ThreadLocal { @Override protected Object initialValue() { // return \"我是默认值,第⼀次返回不再为null\"; return new Date().getTime(); }} package com.it.po.thread10;import java.util.Date;public class Tool3 { public static ThreadLocalExt t1 =new ThreadLocalExt();} package com.it.po.thread10; public class ThreadA3 extends Thread{ @Override public void run() { super.run(); try { for(int i=0;i<10;i++) { System.out.println(\"A3 get value \" + Tool3.t1.get()); Thread.sleep(200);//添加完将cpu让给其他线程 } } catch (InterruptedException e) { e.printStackTrace(); } }} package com.it.po.thread10;public class Run9 { public static void main(String[] args) throws InterruptedException { for(int i=0;i<10;i++) { System.out.println(\"main get value \" + Tool3.t1.get()); Thread.sleep(200);//添加完将cpu让给其他线程 } Thread.sleep(5000); ThreadA3 threadA3 = new ThreadA3(); threadA3.start(); }} main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862main get value 1575171563862A3 get value 1575171570865A3 get value 1575171570865 A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865A3 get value 1575171570865 ⼆、InheritableThreadLocal的使⽤ InheritableThreadLocal可以让⼦线程从⽗线程中取得值 package com.it.po.thread10;import java.util.Date; public class InheritableThreadLocalExt extends InheritableThreadLocal { @Override protected Object initialValue() { return new Date ().getTime(); }} package com.it.po.thread10; public class Tool4 { public static InheritableThreadLocalExt t4 =new InheritableThreadLocalExt();} package com.it.po.thread10; public class ThreadA4 extends Thread{ @Override public void run() { super.run(); try { for(int i=0;i<10;i++) { System.out.println(\"A4 get value \" + Tool4.t4.get()); Thread.sleep(200);//添加完将cpu让给其他线程 } } catch (InterruptedException e) { e.printStackTrace(); } }} package com.it.po.thread10;public class Run10 { public static void main(String[] args) throws InterruptedException { for(int i=0;i<10;i++) { System.out.println(\"main get value \" + Tool4.t4.get()); Thread.sleep(200);//添加完将cpu让给其他线程 } Thread.sleep(5000); ThreadA4 threadA4 = new ThreadA4(); threadA4.start(); }} main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033main get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033 A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033A4 get value 1575177904033 对值继承进⾏修改 package com.it.po.thread10;import java.util.Date; public class InheritableThreadLocalExt extends InheritableThreadLocal { @Override protected Object initialValue() { return new Date ().getTime(); } @Override protected Object childValue(Object parentValue) { return parentValue +\" 我在⼦线程加的\"; }} main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746main get value 1575178136746 A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的A4 get value 1575178136746 我在⼦线程加的 还需要注意: 使⽤ InheritableThreadLocal的时候,如果⼦线程在取得值的同时, 主线程将InheritableThreadLocal 中的值进⾏修改,那么⼦线程得到的值还是旧的值。 因篇幅问题不能全部显示,请点此查看更多更全内容