<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.2.0</version>
</dependency>
package com.jmdf.world;
import com.alibaba.ttl.TransmittableThreadLocal;
public class test01 {
private static ThreadLocal a =new ThreadLocal();
private static ThreadLocal b =new InheritableThreadLocal();
private static ThreadLocal d = new TransmittableThreadLocal();
private static int c = 0;
public static void main(String[] args) {
new Thread(() -> {
a.set(1);
b.set(1);
c = 1;
d.set(1);
new Thread(() -> {
System.out.println("父线程赋值:1,子线程拿到的值");
System.out.println("ThreadLocal------"+a.get());
System.out.println("InheritableThreadLocal-------"+b.get());
System.out.println("静态成员变量-------------------"+c);
System.out.println("TransmittableThreadLocal-------"+d.get());
}).start();
}).start();
}
}
父线程赋值:1,子线程拿到的值
ThreadLocal------null
InheritableThreadLocal-------1
静态成员变量-------------------1
TransmittableThreadLocal-------1
PublicTransmittableThreadLocal
package com.jmdf.world;
import com.alibaba.ttl.TransmittableThreadLocal;
import static java.lang.Thread.sleep;
public class PublicTransmittableThreadLocal {
private static ThreadLocal tl = new TransmittableThreadLocal<>();
public static void main(String[] args) {
new Thread(() -> {
String mainThreadName = "main_01";
tl.set(1);
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
sleep(1L); //确保上面的会在tl.set执行之前执行
tl.set(2); // 等上面的线程池第一次启用完了,父线程再给自己赋值
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
String mainThreadName = "main_02";
tl.set(3);
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
sleep(1L); //确保上面的会在tl.set执行之前执行
tl.set(4); // 等上面的线程池第一次启用完了,父线程再给自己赋值
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
}).start();
System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
}).start();
}
private static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-Thread-3, 变量值=1
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-Thread-9, 变量值=2
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-Thread-6, 变量值=3
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-Thread-5, 变量值=3
线程名称-Thread-1, 变量值=4
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-Thread-11, 变量值=4
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-Thread-12, 变量值=2
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-Thread-8, 变量值=2
线程名称-Thread-0, 变量值=2
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-Thread-13, 变量值=4
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-Thread-4, 变量值=1
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-Thread-2, 变量值=3
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-Thread-10, 变量值=4
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-Thread-7, 变量值=1
TestTransmittableThreadLocal
package com.jmdf.world;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestTransmittableThreadLocal {
// 需要注意的是,使用TTL的时候,要想传递的值不出问题,线程池必须得用TTL加一层代理(下面会讲这样做的目的)
private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));
private static ThreadLocal tl = new TransmittableThreadLocal<>(); //这里采用TTL的实现
public static void main(String[] args) {
new Thread(() -> {
String mainThreadName = "main_01";
tl.set(1);
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
sleep(1L); //确保上面的会在tl.set执行之前执行
tl.set(2); // 等上面的线程池第一次启用完了,父线程再给自己赋值
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
}).start();
new Thread(() -> {
String mainThreadName = "main_02";
tl.set(3);
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
sleep(1L); //确保上面的会在tl.set执行之前执行
tl.set(4); // 等上面的线程池第一次启用完了,父线程再给自己赋值
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
executorService.execute(() -> {
sleep(1L);
System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
});
System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
}).start();
}
private static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-pool-1-thread-1, 变量值=1
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-pool-1-thread-2, 变量值=3
线程名称-Thread-1, 变量值=4
线程名称-Thread-0, 变量值=2
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-pool-1-thread-1, 变量值=3
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-pool-1-thread-2, 变量值=1
本地变量改变之前(1), 父线程名称-main_01, 子线程名称-pool-1-thread-2, 变量值=1
本地变量改变之前(3), 父线程名称-main_02, 子线程名称-pool-1-thread-1, 变量值=3
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-pool-1-thread-1, 变量值=4
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-pool-1-thread-2, 变量值=2
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-pool-1-thread-2, 变量值=2
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-pool-1-thread-1, 变量值=4
本地变量改变之后(4), 父线程名称-main_02, 子线程名称-pool-1-thread-2, 变量值=4
本地变量改变之后(2), 父线程名称-main_01, 子线程名称-pool-1-thread-1, 变量值=2