JAVA多线程-线程间通信(五)-类ThreadLocal的使用

来源:互联网 发布:elasticsearch5 linux 编辑:程序博客网 时间:2024/05/21 15:43

类ThreadLocal的使用

    变量值的共享可以使用public static的形式,所有的线程都是用同一个public static变量。如果想实现每一个线程都有自己的共享变量该如何解决呢?

    类ThreadLocal主要解决的是:每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每一个线程的私有数据。

    1、方法get()与null

package org.jksoft.thread.threadLocal;/** * 测试一:ThreadLocal的get()方法与null * @author mcl * * 2016-2-21-上午10:09:36 */public class Test1 {public static ThreadLocal t = new ThreadLocal();public static void main(String[] args) {if(t.get()==null){System.out.println("从未存放过值......");t.set("我存放的值");}System.out.println(t.get());System.out.println(t.get());}}
     运行结果

    结论

      从上面的结果中来看,第一次调用t对象的get()方法,返回值为null,通过调用set()方法赋值后,顺利取出值并打印到控制台上。类ThreadLocal解决的是变量在不同线程间的隔离性,也就是不同线程用你有自己的值,不同线程中的值,是可以放到ThreadLocal类中进行保存的。

     2、验证线程变量的隔离型

package org.jksoft.thread.threadLocal;/** * 测试二:验证线程变量的隔离性 *  * @author mcl *  *         2016-2-21-上午10:09:36 */public class Test2 {//主线程:启动线程A和线程B,自己从ThreadLocal中取值public static void main(String[] args) {new ThreadA().start();new ThreadB().start();for (int i = 0; i < 100; i++) {try {Tools.t.set("Main SET: " + (i + 1));System.out.println("Main GET: " + Tools.t.get());Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class ThreadA extends Thread {public void run() {for (int i = 0; i < 100; i++) {try {Tools.t.set("ThreadA SET: " + (i + 1));System.out.println("ThreadA GET: " + Tools.t.get());Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class ThreadB extends Thread {public void run() {for (int i = 0; i < 100; i++) {try {Tools.t.set("ThreadB SET: " + (i + 1));System.out.println("ThreadB GET: " + Tools.t.get());Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class Tools {public static ThreadLocal t = new ThreadLocal();}
   结果

      

       结果分析

           我们可以看到,虽然三个线程都在t对象中set()数据值,但每个线程还是能取出自己的数据。

 3、我们如何解决,让ThreadLocal的对象中存在默认值,而不是null呢?

package org.jksoft.thread.threadLocal;/** * 测试三,为ThreadLocal的对象添加默认值,而不是null *  * @author mcl *  *         2016-2-21-上午10:09:36 */public class Test3 {public static MyThreadLocal t = new MyThreadLocal();public static void main(String[] args) {if(t.get()==null){System.out.println("我没有被初始化");t.set("测试一下");}System.out.println(t.get());System.out.println(t.get());}}class MyThreadLocal extends ThreadLocal{@Overrideprotected Object initialValue() {// TODO Auto-generated method stubreturn "我已经被初始化了,不再为null值";}}
   结果展示

        

 

4、类InheritableThreadLocal的使用

      使用类InheritableThreadLocal可以在子线程中取得父线程继承下来的值。

   测试案例:

package org.jksoft.thread.threadLocal;import java.util.Date;/** * 测试四、InheritableThreadLocal的使用 *  * @author mcl *  *         2016-2-21-上午10:09:36 */public class Test4 {public static void main(String[] args) {for(int i=0;i<10;i++){System.out.println("Main :"+Tool.t.get());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}new ThreadC().start();}}class ThreadC extends Thread{public void run(){for(int i=0;i<10;i++){System.out.println("ThreadC :"+Tool.t.get());try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class InheritableThreadLocalExt extends InheritableThreadLocal{@Overrideprotected Object initialValue() {// TODO Auto-generated method stubreturn new Date().getTime();}@Overrideprotected Object childValue(Object parentValue) {// TODO Auto-generated method stubreturn parentValue+"我在子线程添加的";}}class Tool{public static InheritableThreadLocalExt t = new InheritableThreadLocalExt();}

   测试结果

  

  注意:如果子线程在取得值的同时,主线程将InheritableThreadLocal中的值进行更改,那么子线程取到的值还是旧值。

修改Test4中的main方法如下,我们再来查看一下运行结果:

public static void main(String[] args) {for(int i=0;i<10;i++){System.out.println("Main :"+Tool.t.get());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}new ThreadC().start();Tool.t.set(new Date().getTime());for(int i=0;i<10;i++){System.out.println("Main :"+Tool.t.get());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
   结果如下:截取部分结果

        


0 0
原创粉丝点击