接上篇,TTL篇-TTL的使用-CSDN博客
TtlAgent是什么
ttl使用的典型代码是如下所示,
@Data
@AllArgsConstructor
public static class Bean {
private String name;
}
@Test
public void testBean() throws InterruptedException {
TransmittableThreadLocal<Bean> transmittableThreadLocal = new TransmittableThreadLocal<>();
transmittableThreadLocal.set(new Bean("a"));
ExecutorService executorService = Executors.newFixedThreadPool(2);
TtlExecutors.getTtlExecutor(executorService).execute(() -> {
System.out.println("初始拷贝:" + transmittableThreadLocal.get());
Bean bean = transmittableThreadLocal.get();
bean.setName("a1");
});
Thread.sleep(1000);
TtlExecutors.getTtlExecutor(executorService).execute(() -> System.out.println("初始拷贝:" + transmittableThreadLocal.get()));
}
为了使用TransmittableThreadLocal,需要配合TtlExecutors和TtlRunnable。所以在生成上使用的话多有不变,能不能有一个方法对于默认的java线程池进行增强,使得对于普通java线程池,提交的任务,默认使用的TtlRunnable;
官方提供了解决方案,TtlAgent。
TtlAgent的使用效果
如下代码,因为,使用默认的线程池,提交的任务,就会变成TTlRunanle任务,所以打印正常打印出a;
public class TtlAgentTest {
public static void main(String[] args) {
TransmittableThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
transmittableThreadLocal.set("a");
ThreadPoolExecutor threadPoolExecutor = new
ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(100));
AtomicInteger a = new AtomicInteger();
threadPoolExecutor.execute(() -> {
System.out.println(transmittableThreadLocal.get());
});
}
}
怎么使用TtlAgent
<dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.2.0</version> </dependency>
需要指定java启动参数,
-javaagent:D:\maven_jar\com\alibaba\transmittable-thread-local\2.2.0\transmittable-thread-local-2.2.0.jar -Xbootclasspath/a:D:\maven_jar\com\alibaba\transmittable-thread-local\2.2.0\transmittable-thread-local-2.2.0.jar
然后就可以正常跑TtlAgentTest 用例了。
参数详解:
-javaagent:这个是指定javaAgent代理的jar包
-Xbootclasspath:因为修饰了JDK
标准库的类ThreadPoolExecutor,标准库由bootstrap class loader
加载;修饰后的JDK
类引用了TTL
的代码,所以Java Agent
使用方式下TTL Jar
文件需要配置到boot class path
上。
实现原理:
可以通过debug看到,增强的代码实现,$1 = com.alibaba.ttl.TtlRunnable.get($1, false, true);
结论
- 通过使用TtlAgent,可以增强ThreadPoolExecutor线程池,默认提交的任务,会被
TtlRunnable get(),转换TTtlRunnable任务;
- 对于javaAgent需要增强jdk类库的代码,需要使用-Xbootclasspath,让agent的代码bootstrapClassLoader加载,否则默认的类加载器是systemClassLoader/appClassLoader。