子线程是会继承父线程的数据的。。。。但是记住,该类是会有,线程池中线程的复用问题的,,所以在一定情况下还是需要代码使用者自己将东西卸载掉,这种还是使用阿里巴巴的TTL作为替换吧,这个ttl不存在线程池的复用问题,不过线程池需要额外包装一下

  1. public class InheritableThreadLocalDemo {
  2. static ThreadLocal<String> local = new ThreadLocal<>();
  3. static ThreadLocal<String> local2 = new InheritableThreadLocal<>();
  4. @Test
  5. public void test1() {
  6. local.set("haode");
  7. local2.set("haode");
  8. MyThread myThread = new MyThread();
  9. myThread.start();
  10. MyThread2 myThread2 = new MyThread2();
  11. myThread2.start();
  12. local.set("xxxx");
  13. local2.set("xxx");
  14. }
  15. static class MyThread extends Thread {
  16. public void run() {
  17. System.out.println(local.get());
  18. }
  19. }
  20. static class MyThread2 extends Thread {
  21. @Override
  22. public void run() {
  23. System.out.println(local2.get());
  24. }
  25. }
  26. }

ttl

代码有部分是参考网上,如下情况,只有线程池被包装,然后采用TTL方式,才能够解决所有的问题

  1. private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));
  2. private static ExecutorService executorService1 = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));
  3. // private static ThreadLocal tl = new InheritableThreadLocal(); //这里采用TTL的实现
  4. private static ThreadLocal tl = new TransmittableThreadLocal(); //这里采用TTL的实现
  5. public static void main(String[] args) {
  6. new Thread(() -> {
  7. String mainThreadName = "main_01";
  8. tl.set(1);
  9. executorService.execute(() -> {
  10. sleep(1L);
  11. executorService1.execute(() -> {
  12. sleep(1L);
  13. System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  14. });
  15. });
  16. executorService.execute(() -> {
  17. sleep(1L);
  18. executorService1.execute(() -> {
  19. sleep(1L);
  20. System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  21. });
  22. });
  23. executorService.execute(() -> {
  24. sleep(1L);
  25. executorService1.execute(() -> {
  26. sleep(1L);
  27. System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  28. });
  29. });
  30. sleep(1L); //确保上面的会在tl.set执行之前执行
  31. tl.set(2); // 等上面的线程池第一次启用完了,父线程再给自己赋值
  32. executorService.execute(() -> {
  33. sleep(1L);
  34. executorService1.execute(() -> {
  35. sleep(1L);
  36. System.out.println(String.format("本地变量改变之前(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  37. });
  38. });
  39. executorService.execute(() -> {
  40. sleep(1L);
  41. executorService1.execute(() -> {
  42. sleep(1L);
  43. System.out.println(String.format("本地变量改变之前(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  44. });
  45. });
  46. executorService.execute(() -> {
  47. sleep(1L);
  48. executorService1.execute(() -> {
  49. sleep(1L);
  50. System.out.println(String.format("本地变量改变之前(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  51. });
  52. });
  53. System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
  54. }).start();
  55. new Thread(() -> {
  56. String mainThreadName = "main_02";
  57. tl.set(3);
  58. executorService.execute(() -> {
  59. sleep(1L);
  60. executorService1.execute(() -> {
  61. sleep(1L);
  62. System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  63. });
  64. });
  65. executorService.execute(() -> {
  66. sleep(1L);
  67. executorService1.execute(() -> {
  68. sleep(1L);
  69. System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  70. });
  71. });
  72. executorService.execute(() -> {
  73. sleep(1L);
  74. executorService1.execute(() -> {
  75. sleep(1L);
  76. System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  77. });
  78. });
  79. sleep(1L); //确保上面的会在tl.set执行之前执行
  80. tl.set(4); // 等上面的线程池第一次启用完了,父线程再给自己赋值
  81. executorService.execute(() -> {
  82. sleep(1L);
  83. executorService1.execute(() -> {
  84. sleep(1L);
  85. System.out.println(String.format("本地变量改变之前(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  86. });
  87. });
  88. executorService.execute(() -> {
  89. sleep(1L);
  90. executorService1.execute(() -> {
  91. sleep(1L);
  92. System.out.println(String.format("本地变量改变之前(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  93. });
  94. });
  95. executorService.execute(() -> {
  96. sleep(1L);
  97. executorService1.execute(() -> {
  98. sleep(1L);
  99. System.out.println(String.format("本地变量改变之前(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
  100. });
  101. });
  102. System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
  103. }).start();
  104. }
  105. private static void sleep(long time) {
  106. try {
  107. Thread.sleep(time);
  108. } catch (InterruptedException e) {
  109. e.printStackTrace();
  110. }
  111. }