• 八、ThreadLocal


    先看示例:

    public class ThreadTest{
    
        private static int num1 = 0;
        @Test
        public void m1(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        num1= new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()+": data : "+num1);
                        new A();
                    }
                }).start();
            }
        }
        
        class A{
            public A() {
                System.out.println("A :"+Thread.currentThread().getName()+" data : "+num1);
            }
        }
        
    
    }

    上面示例中,定义了一个类变量num1,创建两个线程分别给num1赋随机值然后打印,在内部类A中也对num1的值进行打印。整个过程中,变量num1为所有线程所共享,只要有一个线程将其值改变,其它线程的值也会跟着改变。那么问题就来了,在很多时候,我们在一个线程中处理的数据,仅希望它在当前线程中有效,而不受其它线程的影响。也就是说,数据仅在当前线程中传播。那么,该如何实现呢?

    public class ThreadTest {
        /**
         * 当以一个map,用来存储当前线程的数据
         */
        private static Map<Thread,Integer> map = new HashMap<Thread,Integer>();
        @Test
        public void m2(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num2 = new Random().nextInt();
                        map.put(Thread.currentThread(), num2);  //将值绑定到当前线程中。
                        System.out.println(Thread.currentThread().getName()+": data : "+num2);
                        new B();
                    }
                }).start();
            }
        }
        class B{
            public B() {
                int num2 = map.get(Thread.currentThread());  //取出当前线程的共享变量
                System.out.println("B :"+Thread.currentThread().getName()+" data : "+num2);
            }
        }
    
    }

    上面的示例中,已经实现了在线程的范围内共享。但是,灵活性不足。在lang包下已经为我们实现了线程局部变量的类ThreadLocal。

    public class ThreadLocal {
        /**
         * 创建一个线程局部变量
         */
        private static ThreadLocal<Integer> local = new ThreadLocal<Integer>();
        @Test
        public void m3(){
            for(int i = 0 ;i<2;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num3 = new Random().nextInt();
                        local.set(num3);  //线程局部变量赋值。
                        System.out.println(Thread.currentThread().getName()+": data : "+num3);
                        new C();
                    }
                }).start();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        class C{
            public C() {
                int num3 = local.get();  //取出当前线程的局部变量
                System.out.println("C :"+Thread.currentThread().getName()+" data : "+num3);
            }
        }
    
    }

    版本四:这样写的好处自己体会。

    public class ThreadLocalTest2 {
            @Test
        public void m4(){
            for(int i = 0 ;i<5;i++){
                new Thread(new Runnable(){
                    @Override
                    public void run() {
                        int num4 = new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()+": data : "+num4);
                        D d = D.getD();
                        d.setData(num4);
                        d.printD();
                    }
                }).start();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 将线程局部变量封装到一个类里面
     */
    class D{
        private static ThreadLocal<D> current= new ThreadLocal<D>();
        
        private int data;
        
        private D(){}
        
        public static D getD(){
            if(current.get() == null){
                current.set(new D());
            }
            return current.get();
        }
        
        public int getData() {
            return data;
        }
        public void setData(int data) {
            this.data = data;
        }
        
        public void printD(){
            System.out.println(Thread.currentThread()+": D : data:"+data);
        }
    }
  • 相关阅读:
    c语言学习之基础知识点介绍(十八):几个修饰关键字和内存分区
    c语言学习之基础知识点介绍(十七):写入读取结构体、数组、结构体数组
    c语言学习之基础知识点介绍(十六):文件操作
    c语言学习之基础知识点介绍(十五):函数的指针
    c语言学习之基础知识点介绍(十四):指针的进阶
    c语言学习之基础知识点介绍(十三):枚举的介绍和使用
    c语言学习之基础知识点介绍(十二):结构体的介绍
    c语言学习之基础知识点介绍(十一):字符串的介绍、使用
    c语言学习之基础知识点介绍(十):内存空间模型、地址解释及指针变量
    c语言学习之基础知识点介绍(十):数组
  • 原文地址:https://www.cnblogs.com/futiansu/p/5616001.html
Copyright © 2020-2023  润新知