带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(8)https://developer.aliyun.com/article/1340061?groupCode=taobaotech
鹰眼上下文参数传递
/** * 在主线程中,开启鹰眼异步模式,并将ctx传递给多线程任务3 **/ // 防止鹰眼链路丢失,需要传递 RpcContext_inner ctx = EagleEye.getRpcContext(); // 开启异步模式 ctx.setAsyncMode(true); 8 /** * 在线程池任务线程中,设置鹰眼rpc环境 **/ private void runTask() { try { EagleEye.setRpcContext(ctx); // do something... } catch (Exception e) { log.error("requestError, params: {}", this.params, e); } finally { // 判断当前任务是否是主线程在运行,当Rejected策略为CallerRunsPolicy的时候,核对当前线程if (mainThread != Thread.currentThread()) { EagleEye.clearRpcContext(); } } }
ThreadLocal线程变量概述
什么是ThreadLocal
ThreadLocal类提供了线程本地变量(thread-local variables),这些变量不同于普通的变量,访问线程本地变量的每个线程(通过其get或set方法)都有其自己的独立初始化的变量副本,因此ThreadLocal没有多线程竞争的问题,不需要单独进行加锁。
ThreadLocal使用场景
- 每个线程都需要有属于自己的实例数据(线程隔离);
- 框架跨层数据的传递;
- 需要参数全局传递的复杂调用链路的场景;
- 数据库连接的管理,在AOP的各种嵌套调用中保证事务的一致性;
ThreadLocal的原理与实践
对于ThreadLocal而言,常用的方法有get/set/initialValue 3个方法。
众所周知,在java中SimpleDateFormat有线程安全问题,为了安全地使用SimpleDateFormat,除了1)创建SimpleDateFormat局部变量;和2)加同步锁 两种方案外,我们还可以使用3)ThreadLocal的方案:
/** * 使用 ThreadLocal 定义一个全局的 SimpleDateFormat 3 */ private static ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 9 } }; // 用法 String dateString = simpleDateFormatThreadLocal.get().format(calendar.getTime());