zoukankan      html  css  js  c++  java
  • 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); 结果



    
    
  • 相关阅读:
    文字有阴影效果
    asp.net(c#)将彩色图片变灰阶图片
    C#异步调用的方法
    PHP获取指定月份的第一天开始和最后一天结束的时间戳函数
    php 获取当前用户的IP
    网站前端性能优化
    grep命令的使用
    学C++的经验总结
    主键、唯一键与唯一索引的区别
    shell的比较运算符
  • 原文地址:https://www.cnblogs.com/sweetchildomine/p/8807059.html
Copyright © 2011-2022 走看看