• TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题.


    ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑

    TransmittableThreadLocal 原理

    之前为了能让InheritableThreadLocal 正确传递,不得不每次

    ExecutorService executor = Executors.newFixedThreadPool(>=[任务线程数]);
    或者直接new Thread.

    这样不仅引起性能损耗,并且如果并发上来了,会造成不必要的上下文切换.还必须用信号量做并发控制.
    偶然发现 阿里开源 TransmittableThreadLocal 可以解决此问题.
    以下来实验一下
    /**
     * User: laizhenwei
     * Date: 2018-04-12 Time: 10:07
     * Description:
     */
    public class Ttl {
    
        static ExecutorService executorService = Executors.newFixedThreadPool(1);
    
        public static void main(String[] args) {
            //子线程每次new 所以会复制线程的InheritableThreadLocal,结果正确
    //        withoutThreadPool(10);
            //因线程池复用线程,不会每次new 所以不会更新父线程InheritableThreadLocal 的值,导致结果错误
            withThreadPool(10);
        }
    
        public static void withoutThreadPool(int c){
            for(int i=0;i<c;i++){
                Integer var1 = (int)(Math.random()*100);
                Integer var2 = (int)(Math.random()*100);
                MyContextHolder.set(var1);
                threadRun(var1,var2);
            }
        }
    
        public static void withThreadPool(int c){
            for(int i=0;i<c;i++){
                Integer var1 = (int)(Math.random()*100);
                Integer var2 = (int)(Math.random()*100);
                MyContextHolder.set(var1);
                threadPoolExecute(var1,var2);
            }
        }
    
        public static void threadRun(Integer var1,Integer var2){
            new Thread(()->assert1(var1,var2)).start();
        }
    
        public static void threadPoolExecute(Integer var1,Integer var2){
                    executorService.execute(()->assert1(var1,var2));
        }
    
    
        public static void assert1(Integer var1,Integer var2){
                System.out.println(MyContextHolder.get()*var2==var1*var2);
        }
    
    
        public static class MyContextHolder{
    
           private static ThreadLocal<Integer> stringThreadLocal = new InheritableThreadLocal<>();
    
            public static void set(Integer data) {
                stringThreadLocal.set(data);
            }
    
            public static Integer get() {
                return stringThreadLocal.get();
            }
        }
    
    }
    withoutThreadPool(10)输出结果

    withThreadPool(10); 输出结果

    解决方式

    pom引入

            <!-- https://mvnrepository.com/artifact/com.alibaba/transmittable-thread-local -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>transmittable-thread-local</artifactId>
                <version>2.2.0</version>
            </dependency>

    修改MyContextHolder

        public static class MyContextHolder{
    
            private static ThreadLocal<Integer> stringThreadLocal = new TransmittableThreadLocal<>();
    
    //       private static ThreadLocal<Integer> stringThreadLocal = new InheritableThreadLocal<>();
    
            public static void set(Integer data) {
                stringThreadLocal.set(data);
            }
    
            public static Integer get() {
                return stringThreadLocal.get();
            }
        }

    修改threadPoolExecute

        public static void threadPoolExecute(Integer var1,Integer var2){
            //使用TransmittableThreadLocal 解决
            executorService.execute(TtlRunnable.get(()->assert1(var1,var2)) );
    //                executorService.execute(()->assert1(var1,var2));
        }

    运行 withThreadPool(10); 结果



    
    
  • 相关阅读:
    博客背景美化——动态雪花飘落
    尼姆博弈+SG函数
    2016 CCPC-Final-Wash(优先队列+贪心)
    【php】---mysql语法增、删、改、查---【巷子】
    【php】---mysql---基本操作及使用---【巷子】
    【Object.prototype.toString.call()】---判断某个对象属于哪种内置类型------【巷子】
    【webpack】---模块打包机webpack基础使用---【巷子】
    设计模式---003代理模式---【巷子】
    设计模式---002适配模式---【巷子】
    设计模式---001单例模式---【巷子】
  • 原文地址:https://www.cnblogs.com/sweetchildomine/p/8807059.html
Copyright © 2020-2023  润新知