zoukankan      html  css  js  c++  java
  • ThreadLocal的功能测试的代码,以及对照组的测试的代码

    ThreadLocal会在每个线程内创建一个变量的副本对象,每个线程都是操作自己的那个变量

    但是搜了一圈代码并没有发现好的代码示例,大部分都是讲原理和逻辑,有少部分写了代码的感觉自己都没搞懂,那个代码跑下来也不能证明ThreadLocal的功能

    B站有up给出了工具类的ThreadLocal应用代码,感觉不错,但是比较复杂一些些。而且代码不完整

    我找到了一个博主的代码,稍作修饰,感觉应该能够证明ThreadLocal的功能,并且我增加了一个对照组

    原博如下:https://www.cnblogs.com/codechange/p/8652352.html

    我的代码如下

    package com.interview.bintest.ThreadLoca;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 测试ThreadLocal的功能
     */
    public class ThreadLocalTest {
    
        //首先创建一个全局静态变量ThreadLocal,这样无论创建多少个类对象,都只有一个ThreadLocal变量
        private  static ThreadLocal<List<String>> threadLocal = new ThreadLocal<>();
    
        //设置一个存储ThreadLocal数据的方法
        public void setThreadLocal(List<String> value) {
    
            threadLocal.set(value);
        }
    
        //设置一个获取ThreadLocal数据的方法,因为存储的是list集合,所以对集合也进行一下遍历
        public void getThreadLocal() {
    
            threadLocal.get().forEach(name -> System.out.println(Thread.currentThread().getName()+"###" + name ));
        }
    
        //写一个main方法
        public static void main(String[] args) throws InterruptedException {
    
            //创建一个包含ThreadLocal属性的类的实例
            final ThreadLocalTest localTest = new ThreadLocalTest();
    
            //创建第一个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //第一个线程创建一个list集合作为值存入threadlocal
                    List<String> str1 = new ArrayList<String>();
                    //往第一个集合中存入字符串类型的数字
                    str1.add("1");
                    str1.add("2");
                    str1.add("3");
                    //将list集合存入threadlocal
                    //因为只有一个localTest对象,也只有一个threadlocal,所以多个线程用的是一个类中相同的“threadlocal变量”
                    localTest.setThreadLocal(str1);
                    //提示已经存入成功
                    System.out.println("线程t1存入成功");
                    //存入之后线程睡3秒,保证多个线程都已经存入threadlocal再get()输出
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //遍历Threadlocal中的list
                    localTest.getThreadLocal();
                }
            },"t1").start();
    
            //创建第二个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //和上面的线程相同,创建一个list集合存入
                    List<String> str2 = new ArrayList<String>();
                    //存入字符串类型的a和b
                    str2.add("a");
                    str2.add("b");
                    //将list存入threadlocal
                    //因为只有一个localTest对象,也只有一个threadlocal,所以多个线程用的是一个类中相同的“threadlocal变量”
                    localTest.setThreadLocal(str2);
                    //提示已经存入成功
                    System.out.println("t2已经存入成功");
                    //同样的线程睡3秒再输出
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    localTest.getThreadLocal();
                }
            },"t2").start();
        }
    
    }

    最后的输出结果为

    线程t1存入成功
    t2已经存入成功
    t1###1
    t1###2
    t1###3
    t2###a
    t2###b

    可以看到,用的同一个threadlocal的变量,但是里面的数据不共享

    --------------------------------------------------------------对照组----------------------------------------------------------------------

    我增加了一个对照组,使用的是HashMap,因为ThreadLocal底层用的是Entry数组,而HashMap底层用的是Node数组,是Entry的子类,两个是比较像的,而且ThreadLocal用于存储数据的那个内部类就叫做ThreadLocalMap

    ThreadLocalMap的key值用的是当前线程的ThreadLocal对象,那我对照组就用当前线程名来作为key了

    package com.interview.bintest.ThreadLoca;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Set;
    
    public class ThreadLocalControlTest {
        //首先创建一个全局静态变量HashMap,这样无论创建多少个类对象,都只有一个HashMap变量
        private static HashMap<String,List<String>> hashMap = new HashMap<>();
    
        //设置一个存储HashMap数据的方法
        public void putHashMap(String name,List<String> value) {
    
            hashMap.put(name,value);
        }
    
        //设置一个获取HashMap数据的方法,因为存储的是list集合,所以对集合也进行一下遍历
        public void getHashMap() {
            for(String name : hashMap.keySet()){
                System.out.println(Thread.currentThread().getName()+"###"+hashMap.get(name));
            }
        }
    
        //写一个main方法
        public static void main(String[] args) throws InterruptedException {
    
            //创建一个包含HashMap属性的类的实例
            final ThreadLocalControlTest localControlTest = new ThreadLocalControlTest();
    
            //创建第一个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //第一个线程创建一个list集合作为值存入threadlocal
                    List<String> str1 = new ArrayList<String>();
                    //往第一个集合中存入字符串类型的数字
                    str1.add("1");
                    str1.add("2");
                    str1.add("3");
                    //将list集合存入hashmap
                    //因为只有一个localTest对象,也只有一个hashmap,所以多个线程用的是一个类中相同的“hashmap变量”
                    localControlTest.putHashMap(Thread.currentThread().getName(),str1);
                    //提示已经存入成功
                    System.out.println("线程t1存入成功");
                    //存入之后线程睡3秒,保证多个线程都已经存入threadlocal再get()输出
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //遍历Threadlocal中的list
                    localControlTest.getHashMap();
                }
            },"t1").start();
    
            //创建第二个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //和上面的线程相同,创建一个list集合存入
                    List<String> str2 = new ArrayList<String>();
                    //存入字符串类型的a和b
                    str2.add("a");
                    str2.add("b");
                    //将list存入hashmap
                    //因为只有一个localTest对象,也只有一个hashmap,所以多个线程用的是一个类中相同的“hashmap变量”
                    localControlTest.putHashMap(Thread.currentThread().getName(),str2);
                    //提示已经存入成功
                    System.out.println("t2已经存入成功");
                    //同样的线程睡3秒再输出
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    localControlTest.getHashMap();
                }
            },"t2").start();
        }
    
    }

    最终输出结果如下

    线程t1存入成功
    t2已经存入成功
    t1###[1, 2, 3]
    t1###[a, b]
    t2###[1, 2, 3]
    t2###[a, b]

    t1和t2输出的一模一样

    tips:其实还可以在主线程中再输出一次存储数据的threadlocal和hashmap,这样也可以证实结论,因为一共有3个线程,主线程也可以把静态变量进行输出,对比效果也很明显,限于时间问题,我就不做测试了,有兴趣的可以自己测试 

    综上所述,ThreadLocal里的变量各个线程之间互不干扰的结论得到证实

  • 相关阅读:
    关于前端框架讨论的链接
    和BEM的战斗:10个常见问题及如何避免
    BEM —— 源自Yandex的CSS 命名方法论
    JavaScript 语句后应该加分号么?
    彻底搞懂word-break、word-wrap、white-space
    ios UIImageWriteToSavedPhotosAlbum报错 NSPhotoLibraryAddUsageDescription
    Emmet使用手册
    vue-cli入门之项目结构分析
    ios移动端原生滚动条滚动不灵敏问题
    ios点击事件失效
  • 原文地址:https://www.cnblogs.com/skyvalley/p/14527064.html
Copyright © 2011-2022 走看看