ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal 区别,使用场景 示例
总结:
ThreadLocal:set,get 需要再同一个线程中执行,父子线程不支持
InheritableThreadLocal:支持父子线程,不支持线程池
TransmittableThreadLocal :以上都支持
代码示例
1 pom.xml
<!-- 阿里线程传递值 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.3</version>
</dependency>
2 ThreadLocal,InheritableThreadLocal 对比
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
public class InheritableThreadLocalExample {
static Logger logger = LoggerFactory.getLogger(InheritableThreadLocalExample.class);
/**
* 输出结果
* [main] [traceId:] - userName:张三
* [thread1] [traceId:] - userName:null
* @throws InterruptedException
*/
private static void threadLocalTest() throws InterruptedException {
ThreadLocal<String> userNameTL = new ThreadLocal<>();
//这里是主线程,ThreadLocal中设置了值:张三
userNameTL.set("张三");
logger.info("userName:{}", userNameTL.get());
//创建了一个子线程thread1,在子线程中去ThreadLocal中拿值,能否拿到刚才放进去的“张三”呢?
new Thread(() -> {
logger.info("userName:{}", userNameTL.get());
}, "thread1").start();
TimeUnit.SECONDS.sleep(1);
}
/**
* 输出结果
* [main] [traceId:] - userName:张三
* [thread1] [traceId:] - userName:张三
*
* @throws InterruptedException
*/
private static void inheritableThreadLocal() throws InterruptedException {
InheritableThreadLocal<String> userNameItl = new InheritableThreadLocal<>();
//这里是主线程,使用 InheritableThreadLocal.set 放入值:张三
userNameItl.set("张三");
logger.info("userName:{}", userNameItl.get());
//创建了一个子线程thread1,在子线程中去ThreadLocal中拿值,能否拿到刚才放进去的“张三”呢?
new Thread(() -> {
logger.info("userName:{}", userNameItl.get());
}, "thread1").start();
TimeUnit.SECONDS.sleep(1);
}
public static void main(String[] args) throws InterruptedException {
threadLocalTest();
System.out.println();
inheritableThreadLocal();
}
}
3 InheritableThreadLocal ,TransmittableThreadLocal 对比
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TransmittableThreadLocalExample {
static Logger logger = LoggerFactory.getLogger(TransmittableThreadLocalExample.class);
/**
* 输出结果
* [main] [traceId:] - userName:张三
* [pool-1-thread-1] [traceId:] - 第1次获取 userName:张三
* [main] [traceId:] - userName:李四
* [pool-1-thread-1] [traceId:] - 第2次获取 userName:张三
*
* @throws InterruptedException
*/
private static void fangfa_Inheri_test() throws InterruptedException {
InheritableThreadLocal<String> userNameTtl = new InheritableThreadLocal<String>();
// 为了看到效果,这里创建大小为1的线程池,注意这里为1才能方便看到效果
ExecutorService executorService = Executors.newFixedThreadPool(1);
// 主线程中设置 张三
userNameTtl.set("张三");
logger.info("userName:{}", userNameTtl.get());
// 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的张三?
executorService.execute(() -> {
logger.info("第1次获取 userName:{}", userNameTtl.get());
});
TimeUnit.SECONDS.sleep(1);
// 这里放入了李四
userNameTtl.set("李四");
logger.info("userName:{}", userNameTtl.get());
// 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的李四?
executorService.execute(() -> {
// 在线程池中通过 inheritableThreadLocal 拿值,看看能否拿到?
logger.info("第2次获取 userName:{}", userNameTtl.get());
});
TimeUnit.SECONDS.sleep(1);
}
/**
* 输出结果
* [main] [traceId:] - userName:张三
* [pool-1-thread-1] [traceId:] - 第1次获取 userName:张三
* [main] [traceId:] - userName:李四
* [pool-1-thread-1] [traceId:] - 第2次获取 userName:李四
*
* @throws InterruptedException
*/
private static void fangfa_Transmit_test() throws InterruptedException {
TransmittableThreadLocal<String> userNameTtl = new TransmittableThreadLocal<String>();
// 为了看到效果,这里创建大小为1的线程池,注意这里为1才能方便看到效果
ExecutorService executorService = Executors.newFixedThreadPool(1);
// 这里需要用 TtlExecutors.getTtlExecutorService 将原线程池包装下
executorService = TtlExecutors.getTtlExecutorService(executorService);
// 主线程中设置 张三
userNameTtl.set("张三");
logger.info("userName:{}", userNameTtl.get());
// 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的张三?
executorService.execute(() -> {
logger.info("第1次获取 userName:{}", userNameTtl.get());
});
TimeUnit.SECONDS.sleep(1);
// 这里放入了李四
userNameTtl.set("李四");
logger.info("userName:{}", userNameTtl.get());
// 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的李四?
executorService.execute(() -> {
// 在线程池中通过 inheritableThreadLocal 拿值,看看能否拿到?
logger.info("第2次获取 userName:{}", userNameTtl.get());
});
TimeUnit.SECONDS.sleep(1);
}
public static void main(String[] args) throws InterruptedException {
fangfa_Inheri_test();
System.out.println();
fangfa_Transmit_test();
}
}