您的位置:首页 > 编程语言 > Java开发

【Java多线程与并发库】6.ThreadLocal类及应用技巧

2016-10-24 14:15 591 查看
之前我们了解了实现线程范围内数据共享的机制,接下来我们
可以使用JDK5提供的ThreadLocal类,来实现线程范围内数据共享。

ThreadLocal类其实就类似于我们上一次创建的Map。

我们创建一个测试类,来使用ThreadLocal类实现线程范围内数据共享:
我们的类A和类B每次都从线程中获取data值打印,为了保证每次打印的数据是该线程的数据,
类A和类B的数据都从ThreadLocal中获取。

package cn.edu.hpu.test;  

  

import java.util.Random;  

  

public class ThreadTest7 {  

      

    private static Random dandom=new Random();  

    private static ThreadLocal<Integer> x=new ThreadLocal<Integer>();  

  

    public static void main(String[] args) {  

        for(int i=0;i<2;i++){  

            new Thread(new Runnable(){  

                public void run() {  

                    int data=dandom.nextInt();  

                    System.out.println(Thread.currentThread().getName()  

                            +"放入数据:"+data);  

                    x.set(data);  

                    new A().get();  

                    new B().get();  

                }  

                  

            }).start();  

        }  

    }  

      

    static class A{  

        public void get(){  

            System.out.println("A 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+x.get());  

        }  

    }  

      

    static class B{  

        public void get(){  

            System.out.println("B 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+x.get());  

        }  

    }  

}  
结果:



实现了每个线程中的数据共享在每个线程自己的范围内。线程之间的数据不会混杂在一起。

如果有N个变量需要做到线程范围内数据共享,应该如何做到?
一个ThreadLocal只能放一个变量,我们可以使用多个ThreadLocal来实现,
如果共享的数据量过大,我们就把这些数据放在一个对象中,然后在ThreadLocal中
存储这一个对象。

package cn.edu.hpu.test;  

  

import java.util.Random;  

  

public class ThreadTest7 {  

      

    private static Random dandom=new Random();  

    private static ThreadLocal<MyThreadScopeData> MyThreadScopeData=new ThreadLocal<MyThreadScopeData>();  

  

    public static void main(String[] args) {  

        for(int i=0;i<2;i++){  

            new Thread(new Runnable(){  

                public void run() {  

                    int data=dandom.nextInt();  

                    System.out.println(Thread.currentThread().getName()  

                            +"放入数据:"+data);  

                    MyThreadScopeData ScopeData=new MyThreadScopeData();  

                    ScopeData.setName("name"+data);  

                    ScopeData.setAge(data);  

                    MyThreadScopeData.set(ScopeData);  

                    new A().get();  

                    new B().get();  

                }  

                  

            }).start();  

        }  

    }  

      

    static class A{  

        public void get(){  

            System.out.println("A 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+MyThreadScopeData.get().getName()  

                    +MyThreadScopeData.get().getAge());  

        }  

    }  

      

    static class B{  

        public void get(){  

            System.out.println("A 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+MyThreadScopeData.get().getName()  

                    +MyThreadScopeData.get().getAge());  

        }  

    }  

}  

  

class MyThreadScopeData{  

    private String name;  

    private int age;  

    public String getName() {  

        return name;  

    }  

    public void setName(String name) {  

        this.name = name;  

    }  

    public int getAge() {  

        return age;  

    }  

    public void setAge(int age) {  

        this.age = age;  

    }  

}  

结果:



这样就可以在线程范围内共享N中数据了。

上面的设计其实不够好,但是要设计更加优雅一点,不要看到我们使用ThreadLocal的痕迹:

package cn.edu.hpu.test;  

  

import java.util.Random;  

  

public class ThreadTest7 {  

      

    private static Random dandom=new Random();  

    public static void main(String[] args) {  

        for(int i=0;i<2;i++){  

            new Thread(new Runnable(){  

                public void run() {  

                    int data=dandom.nextInt();  

                    System.out.println(Thread.currentThread().getName()  

                            +"放入数据:"+data);  

  

                    MyThreadScopeData.getThreadInstance().setName("name"+data);  

                    MyThreadScopeData.getThreadInstance().setAge(data);  

                    new A().get();  

                    new B().get();  

                }  

                  

            }).start();  

        }  

    }  

      

    static class A{  

        public void get(){  

            System.out.println("A 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+MyThreadScopeData.getThreadInstance().getName()  

                    +MyThreadScopeData.getThreadInstance().getAge());  

        }  

    }  

      

    static class B{  

        public void get(){  

            System.out.println("A 从"+Thread.currentThread().getName()  

                    +"中取的数据:"+MyThreadScopeData.getThreadInstance().getName()  

                    +MyThreadScopeData.getThreadInstance().getAge());  

        }  

    }  

}  

  

class MyThreadScopeData{  

      

    private MyThreadScopeData(){}  

    public static MyThreadScopeData getThreadInstance(){  

        MyThreadScopeData instance=map.get();  

        if(instance==null){  

            instance=new MyThreadScopeData();  

            map.set(instance);  

        }  

        return instance;  

    }  

    private static ThreadLocal<MyThreadScopeData> map =new ThreadLocal<MyThreadScopeData>();  

      

    private String name;  

    private int age;  

    public String getName() {  

        return name;  

    }  

    public void setName(String name) {  

        this.name = name;  

    }  

    public int getAge() {  

        return age;  

    }  

    public void setAge(int age) {  

        this.age = age;  

    }  

}  

这里,我们调用MyThreadScopeData的getThreadInstance方法,就可以取得
与当前线程相关的实例对象。

虽然线程结束后也可以自动释放相关的ThreadLocal变量,但是为了优化内存,
我们的ThreadLocal要在线程结束的时候注销,可以调用ThreadLocal.clear()方法。

出处:http://blog.csdn.net/acmman/article/details/52794523
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐